2010-12-10 28 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); 

希望能幫助你