2011-01-05 20 views
7
//ModelFor(person =>person.Name); 
public void ModelFor<TModel, TValue>(
    Expression<Func<TModel, TValue>> expression) 
{ 
    //Result should be "Name" 
    string nameOfTValue = ????;  
} 
+0

Bạn cần làm rõ, bạn có muốn tên loại TValue hay bạn muốn tên của p tham số trong biểu thức? – casperOne

+0

@casperOne - Tôi đã chỉnh sửa – Freshblood

+0

@casperOne 'TValue' luôn là kiểu trả về và không phải là thông số bình thường. – CodesInChaos

Trả lời

8

EDIT: Sau khi chỉnh sửa, tôi nghĩ bạn muốn tên của thành viên tham gia biểu thức, giả sử tất nhiên biểu thức là biểu thức thành viên ngay từ đầu.

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

Để trở thành mạnh mẽ hơn, bạn có thể làm:

var memberEx = expression.Body as MemberExpression; 

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

string name = memberEx.Member.Name; 

(Không liên quan nữa):

Để có được một System.Type đại diện cho loại kiểu TValue -giá trị, bạn có thể sử dụng toán tử typeof.

Bạn có thể muốn:

typeof(TValue).Name 

Nhưng cũng xem xét các FullNameAssemblyQualifiedName tính nếu cần thiết.

Điều này thực sự không liên quan gì tới các cây biểu thức; bạn có thể sử dụng kỹ thuật này để nhận loại đối số loại cho phương thức chung bất kỳ.

+0

Wow, chúng tôi đã viết hoàn toàn câu trả lời giống hệt nhau – CodesInChaos

+1

Tôi không nghĩ rằng điều này là đúng, tôi nghĩ rằng anh ta muốn tên của tham số trong biểu thức loại TValue. – casperOne

+0

@casperOne: Bạn có thể đúng; Tôi không chắc. Chúng ta hãy chờ để làm rõ. – Ani

9

@Ani: Tôi không nghĩ rằng đây là đúng, tôi nghĩ rằng ông muốn tên của tham số trong sự biểu hiện của kiểu TValue

Nếu điều này là đúng ... làm việc này 1 cấp sâu chỉ nhưng có thể có ích anyway:

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

đây là thực hiện thông minh hơn mà sẽ có thể đối phó với nhiều cấp độ:

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

Cách sử dụng:

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

Một thủ thuật khác, điều này có thể được kết hợp với suy nghĩ độc đáo:

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

Cho phép tính một cách dễ dàng trực tiếp thiết lập, có thể hữu ích cho đồ đạc kiểm tra:

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

Ver đẹp, tôi thực sự thích nó! – Raffaeu

Các vấn đề liên quan