简体   繁体   English

表达 <Func<TModel,TValue> &gt;我怎样才能获得TValue的名字?

[英]Expression<Func<TModel,TValue>> how can i get TValue's name?

//ModelFor(person =>person.Name);
public void ModelFor<TModel, TValue>(
    Expression<Func<TModel, TValue>> expression)
{
    //Result should be "Name"
    string nameOfTValue = ????;     
}

@Ani: I don't think this is right, I think that he wants the name of the parameter in the expression of type TValue @Ani:我不认为这是对的,我认为他想在TValue类型的表达式中使用参数的名称

If this is true... this works 1 level deep only but might be handy anyway: 如果这是真的......这只能在1级深度工作,但无论如何都可能很方便:

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

Here is smarter implementation that should be able to deal with multiple levels: 这是更聪明的实现,应该能够处理多个级别:

 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));
    }
  }

Usage: 用法:

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

Another trick, this can be combined with reflection nicely: 另一个技巧,这可以很好地结合反射:

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;
}

Allows to directly set properties with ease, can be useful for test fixtures: 允许轻松直接设置属性,可用于测试夹具:

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

EDIT : After your edit, I think you are want the name of the member involved in the expression, assuming of course that the expression is a member-expression in the first place. 编辑 :编辑后,我想你想要表达式中涉及的成员的名称,当然假设表达式首先是成员表达式。

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

To be more robust, you can do: 为了更加强大,您可以:

var memberEx = expression.Body as MemberExpression;

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

string name = memberEx.Member.Name;

(Not relevant anymore): (不再相关):

To get a System.Type that represents the type of the TValue type-argument, you can use the typeof operator. 要获取表示TValue类型参数类型的System.Type ,可以使用typeof运算符。

You probably want: 你可能想要:

typeof(TValue).Name

But also consider the FullName and AssemblyQualifiedName properties if appropriate. 但如果合适,还要考虑FullNameAssemblyQualifiedName属性。

This really has nothing to do with expression-trees; 这与表达树无关; you can use this technique to get the type of a type-argument for any generic method. 您可以使用此技术获取任何泛型方法的类型参数的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM