2010-12-10 76 views
3

我想定义就像MVC扩展模板函数的函数TextBoxFor.NET定义函数,它接受一个lambda表达式

该功能的有趣的事情是,我没有指定TProperty类型。 如何在我的函数定义中设置它。

我的代码如下所示:

public class Helper<TItem> 
{ 
    public string GetMemberName(Expression<Func<TItem, TProperty>> expression) 
    { 
     ... returns TProperty.Name 

    } 
} 

实际的问题是,这并不编译...因为它无法找到TProperty类型。

我想要的结果是用类型定义一次类...然后使用函数GetMemberName获取每个成员的名称,如MVC框架。

Helper<Employee> h = new Helper<Employee>(); 
string name = h.GetMemberName(e=>e.Name); 
.... 

我不想在编写代码时指定TProperty类型。基本上它可以是任何对象。

感谢,

拉杜

+0

哥们看到我的答案,也许让你的代码更优雅。 – 2010-12-10 09:44:25

回答

3

这是你所需要的:

public class Helper<TItem> 
{ 
    public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression) 
    { 
     return string.Empty; // I didn't implement it 
    } 
} 

Just ap将<TProperty>挂到您的方法名称以使其通用。和TProperty类型可以从所提供的表达来推断,所以你不必指定其类型使用时可以简单:

Helper<Employee> h = new Helper<Employee>(); 
h.GetMemberName(e=>e.Name); //if Employee has such a property 
+0

非常感谢...您拯救了我的一天:) Linq如何推断我想要对象的任何属性?这是一个惯例吗? – 2010-12-10 09:26:47

+0

@Radu D:如果你想知道类型推断的更多细节,请看'C#语言规范§7.5.2类型推断'。 – 2010-12-10 09:45:51

0

可以使用ModelMetaData类提取从Expression信息。

public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression) { 
    var meta = ModelMetaData.FromLambdaExpression(expression, null); 
    return meta.PropertyName; // Or something else 
} 
1

下面的函数返回一个使用lambda表达式传递给它的任何属性的名称:

public static string Property<T>(Expression<Func<T>> e) 
    { 
     var member = (MemberExpression)e.Body; 
     return member.Member.Name; 
    } 
+0

它只为原始数据类型AFAIK – 2010-12-10 09:16:37

+0

做这项工作它与一个属性的'Type'无关,而是一个属性的'Name'。 – decyclone 2010-12-10 09:18:02

0

我曾经写过这个功能,但我不记得它到底。 但首先委托签名更改为这个Func<T, object>,然后进行简单的数据类型得到表达的身体和它转换为MemberExpression并获得第一个参数

的名称,如果访问的成员是一个复杂的问题,你必须转换表达式正文到一元表达式取第一个参数并将其转换为MemberExpression并执行第一步中的操作。

在调试该功能时使用QuickWatch可能导致您找到解决方案。 值得一提的是,阅读MVC代码中的HtmlHelper可能会有帮助。

编辑: 大致记得

更好的方法是使提供职位月薪也没有必要写这样的功能扩展方法(用,如果你想在适用上的类型约束)了,因为它是从使用推断。

所以你的功能是这样的:

public static class Helper 
{ 
    public static string Item<TItem,TMember>(this TItem obj, Expression<Func<TItem, TMember>> expression) 
    { 
     if (expression.Body is MemberExpression) 
     { 
      return ((MemberExpression)(expression.Body)).Member.Name; 
     } 
     if(expression.Body is UnaryExpression) 
     { 
      return ((MemberExpression)((UnaryExpression)(expression.Body)).Operand).Member.Name; 
     } 
     throw new InvalidOperationException(); 
    } 
} 

所以你的代码会更清洁

Employee emp = new Employee(); 
emp.Item(o=>o.Name); 

希望能帮助你