Action委托参数的自定义属性能否读取?求反射实现技巧
能否读取Action委托参数上的自定义属性?
为什么你的代码执行失败
当你通过lambda创建Action<string, string>实例时,本质是让lambda适配预定义委托Action<T1,T2>的签名。而Action<T1,T2>的Invoke方法是.NET类库预定义的,它的参数根本没有你添加的CustomAttr属性——你的属性只属于lambda表达式的参数,不会被复制到预定义委托的Invoke方法参数上,所以通过simpleAction.GetType().GetMethod("Invoke")拿到的参数自然没有这些属性。
可行的反射技巧:利用表达式树
要读取lambda参数上的自定义属性,你需要借助表达式树(Expression Tree),因为编译器在生成表达式树时会完整保留lambda参数的元数据(包括自定义属性)。示例代码如下:
首先定义你的自定义属性:
public class CustomAttr : Attribute { public string DisplayName { get; set; } }
然后通过表达式树捕获并读取属性:
// 将lambda声明为表达式树类型,而非直接创建Action实例 Expression<Action<string, string>> actionExpr = ( [CustomAttr(DisplayName = "MyFirstArg")] a, [CustomAttr(DisplayName = "MySecondArg")] b) => { }; // 遍历表达式树的参数,获取自定义属性 foreach (var param in actionExpr.Parameters) { var customAttr = param.GetCustomAttribute<CustomAttr>(); // 验证代码: customAttr.ShouldNotBeNull(); customAttr.DisplayName.ShouldBe(param == actionExpr.Parameters[0] ? "MyFirstArg" : "MySecondArg"); }
注意事项
- 如果已经持有一个
Action实例(而非表达式树),无法通过反射获取lambda参数的自定义属性——因为编译后的委托只保存了方法执行的逻辑,丢失了lambda参数的元数据信息(编译器通常不会将lambda参数的属性保留到生成的匿名方法参数上)。 - 只有当委托绑定到显式定义的方法(而非lambda)时,才能通过
Delegate.Method获取方法信息,进而读取参数属性:// 显式定义带属性参数的方法 public void MyMethod([CustomAttr(DisplayName = "Arg1")] string a, [CustomAttr(DisplayName = "Arg2")] string b) { } // 创建委托 Action<string, string> action = MyMethod; // 读取属性 var parameters = action.Method.GetParameters(); foreach (var p in parameters) { var attr = p.GetCustomAttribute<CustomAttr>(); // 可以正常获取到属性 }
内容的提问来源于stack exchange,提问作者divinci
相关产品推荐
相关产品推荐

