You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 16:14:56