如何简化同时传递nameof(资源对象)与资源对象至构造方法的代码
解决方案
你可以通过编译表达式树来同时获取资源的名称和实际值,实现只传一次参数的简化调用。以下是完整的可行实现:
using System.Linq.Expressions; using System.Text; public record ResourceObject { public string Name { get; init; } public byte[] File { get; init; } public string Content { get; init; } // 私有构造方法,限制实例创建入口 private ResourceObject(string name, byte[] file) { Name = name; File = file; Content = Encoding.Default.GetString(file); } public static ResourceObject New(Expression<Func<byte[]>> resourceExpression) { // 解析资源属性名称 if (resourceExpression.Body is not MemberExpression memberExpr) { throw new ArgumentException("请传入资源属性表达式,格式示例:() => Properties.Resources.XXX"); } string resourceName = memberExpr.Member.Name; // 编译表达式并获取资源的实际值 Func<byte[]> getResource = resourceExpression.Compile(); byte[] resourceValue = getResource(); return new ResourceObject(resourceName, resourceValue); } }
调用方式
var test = ResourceObject.New(() => Properties.Resources.SomeResource);
关键细节说明
- 直接约束表达式返回
byte[]类型,避免不必要的类型转换,同时确保传入的是符合要求的资源 - 通过
Compile()方法将表达式树转为可执行委托,调用后即可拿到资源的实际字节数组 - 增加参数校验逻辑,避免传入非法表达式导致空引用或类型错误
如果需要支持更多资源类型,可改为泛型版本并增加类型校验:
public static ResourceObject New<T>(Expression<Func<T>> resourceExpression) where T : class { if (resourceExpression.Body is not MemberExpression memberExpr) { throw new ArgumentException("请传入资源属性表达式,格式示例:() => Properties.Resources.XXX"); } string resourceName = memberExpr.Member.Name; Func<T> getResource = resourceExpression.Compile(); T resourceValue = getResource(); if (resourceValue is not byte[] fileBytes) { throw new ArgumentException("当前仅支持byte[]类型的资源"); } return new ResourceObject(resourceName, fileBytes); }
内容的提问来源于stack exchange,提问作者LorneCash
相关产品推荐
相关产品推荐

