【问题标题】:Expression<Func<TModel,TValue>> how can i get TValue's name?Expression<Func<TModel,TValue>> 如何获得 TValue 的名称?
【发布时间】:2011-01-05 16:04:04
【问题描述】:
//ModelFor(person =>person.Name);
public void ModelFor<TModel, TValue>(
    Expression<Func<TModel, TValue>> expression)
{
    //Result should be "Name"
    string nameOfTValue = ????;     
}

【问题讨论】:

  • 需要澄清一下,是要TValue类型的名称,还是要表达式中的参数名称?
  • @casperOne TValue 始终是返回类型,而不是普通参数。
  • 你可以像这样获取PropertyInfo:stackoverflow.com/questions/671968/…然后使用.Name就可以了

标签: c# .net expression-trees


【解决方案1】:

编辑:编辑后,我认为您想要表达式中涉及的成员的名称,当然首先假设表达式是成员表达式。

((MemberExpression)expression.Body).Member.Name

为了更健壮,您可以这样做:

var memberEx = expression.Body as MemberExpression;

if (memberEx == null)
     throw new ArgumentException("Body not a member-expression.");

string name = memberEx.Member.Name;

(不再相关):

要获得代表TValue 类型参数类型的System.Type,您可以使用typeof 运算符。

你可能想要:

typeof(TValue).Name

但如果合适,还要考虑 FullNameAssemblyQualifiedName 属性。

这真的与表达式树无关;您可以使用这种技术来获取 any 泛型方法的类型参数的类型。

【讨论】:

  • 哇,我们写的答案完全一样
  • 我觉得这不对,我觉得他要的是TValue类型的表达式中的参数名称。
  • @casperOne:你可能是对的;我不知道。让我们等待澄清。
  • 投反对票的人能解释一下吗?也许您想看看编辑时间戳。
【解决方案2】:

@Ani:我觉得这不对,我觉得他想要TValue类型的表达式中的参数名

如果这是真的...这仅适用于 1 级深度,但无论如何可能会很方便:

var nameOfTValue = ((MemberExpression)expression.Body).Member.Name; 

下面是更智能的实现,应该能够处理多个级别:

 public class PropertyName{
    public static string For<T>(
      Expression<Func<T,object>> expression){
      var body=expression.Body;
      return GetMemberName(body);
    }
    public static string For(
      Expression<Func<object>> expression){
      var body=expression.Body;
      return GetMemberName(body);
    }
    public static string GetMemberName(
      Expression expression){
      if(expression is MemberExpression){
        var memberExpression=(MemberExpression)expression;
        if(memberExpression.Expression.NodeType==
           ExpressionType.MemberAccess)
          return GetMemberName(memberExpression.Expression)
            +"."+memberExpression.Member.Name;
        return memberExpression.Member.Name;
      }
      if(expression is UnaryExpression){
        var unaryExpression=(UnaryExpression)expression;
        if(unaryExpression.NodeType!=ExpressionType.Convert)
          throw new Exception(string.Format
            ("Cannot interpret member from {0}",expression));
        return GetMemberName(unaryExpression.Operand);
      }
      throw new Exception
        (string.Format("Could not determine member from {0}",expression));
    }
  }

用法:

var fieldName=PropertyName.For<Customer>(x=>x.Address.Region);
//fieldName==Address.Region

另一个技巧,这可以很好地与反射结合:

public static T Set<T,TProp>(this T o,
   Expression<Func<T,TProp>> field,TProp value){
  var fn=((MemberExpression)field.Body).Member.Name;
  o.GetType().GetProperty(fn).SetValue(o,value,null);
  return o;
}

允许轻松直接设置属性,可用于测试夹具:

var customer=new Customer("firstName","lastName");
customer.Set(x=>x.Name, "different firstName");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    相关资源
    最近更新 更多