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

如何实现仅指定TType即可调用反射获取DescriptionAttribute的泛型方法?

问题描述

我定义了如下类:

public class Demo
{
  [Description("Hello World!")]
  public int SomeProp { get; set; }
}

为了获取属性的Description特性值,我写了下面这个泛型方法:

public string? GetDescription<TType, TProperty>(Expression<Func<TType, TProperty>> expression)
  where TType : class
{
  var memberName  = ((MemberExpression)expression.Body).Member.Name;
  var description = typeof(TType).GetMember(memberName).First()
                    .GetCustomAttribute<DescriptionAttribute>()
                    ?.Description;
  return description;
}

目前调用的时候必须同时指定两个泛型参数:

var description = GetDescription<Demo, string>(x => x.SomeProp);

但我希望能简化成只指定TType的调用方式,让编译器自动推断属性类型:

var description = GetDescription<Demo>(x => x.SomeProp);   // 不需要指定TProperty

现在不指定TProperty就会编译报错:“Using the generic method requires 2 type arguments”,请问该怎么实现这种调用方式?


解决方案

方案一:利用类型推断移除不必要的泛型参数

你的方法逻辑里其实根本没用到TProperty类型,只是需要通过表达式定位到属性成员。可以把表达式参数改成Expression<Func<TType, object>>,这样编译器会自动处理值类型的装箱操作,同时只需要显式指定TType:

public string? GetDescription<TType>(Expression<Func<TType, object>> expression)
  where TType : class
{
    MemberExpression memberExpr;
    // 处理值类型装箱时的表达式包装(此时Body是UnaryExpression)
    if (expression.Body is UnaryExpression unaryExpr)
    {
        memberExpr = (MemberExpression)unaryExpr.Operand;
    }
    else
    {
        memberExpr = (MemberExpression)expression.Body;
    }
    
    var memberName = memberExpr.Member.Name;
    var description = typeof(TType).GetMember(memberName).First()
                      .GetCustomAttribute<DescriptionAttribute>()
                      ?.Description;
    return description;
}

现在就能按你想要的方式调用了:

var description = GetDescription<Demo>(x => x.SomeProp);

方案二:拆分泛型参数到层级结构

如果一定要保留TProperty的泛型约束,可以用一个辅助类拆分泛型参数,让TType显式指定,TProperty通过后续方法自动推断:

// 辅助类,用于承载属性表达式的推断
public class DescriptionGetter<TType> where TType : class
{
    public string? For<TProperty>(Expression<Func<TType, TProperty>> expression)
    {
        var memberName = ((MemberExpression)expression.Body).Member.Name;
        var description = typeof(TType).GetMember(memberName).First()
                          .GetCustomAttribute<DescriptionAttribute>()
                          ?.Description;
        return description;
    }
}

// 入口方法,只需要指定TType
public DescriptionGetter<TType> GetDescription<TType>() where TType : class
{
    return new DescriptionGetter<TType>();
}

调用方式变成:

var description = GetDescription<Demo>().For(x => x.SomeProp);

原方法无法推断的原因

C#的泛型类型推断规则是:要么完全通过方法参数自动推断所有泛型参数,要么显式指定全部泛型参数。当你手动指定了其中一个泛型参数(TType),编译器就会要求你指定所有剩余的泛型参数,不会再自动推断TProperty。所以必须通过上述方式打破这个限制。


内容的提问来源于stack exchange,提问作者lonix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 16:14:50