2011-09-23 101 views
9

我有一個工作設置,它不是強類型的並且依賴於反射。lambda表達式作爲屬性

我有一類,說

class Person{ 

    public string FirstName {get ; set;} 
    public string LastName {get; set;} 
    public int Age {get; set;} 
    ... 
    // some more public properties 
} 

class CellInfo { 
    public string Title {get; set;} 
    public string FormatString {get; set;} 
} 

和我有這樣

Dictionary<string, CellInfo> fields = new Dictionary<string, CellInfo>(); 
fields.Add("FirstName", new CellInfo {Title = "First Name", FormatString = "Foo"}); 
fields.Add("LastName", new CellInfo {Title = "Last Name", FormatString = "Bar"}); 

這是一個簡單的字典,屬性名稱和對一些信息的字典他們。 我把字典用於處理Person實例另一個模塊,我做

Dictionary<string, CellInfo> fields = SomeMethodToGetDictionary(); 
foreach(Person p in someCollection) 
{ 
    foreach(var field in fields) 
    { 
     object cellValue = type(Person).GetProperty(field.Key).GetValue(p, null); 
     // use cellValue and info on field from field.Value somewhere. 
     ... 
    } 
} 

傳遞字符串字段名稱和使用反射的這種方法可行,但我想知道是否有這樣做的一個強類型的方法這個。

我腦子裏想的是什麼,其具有存儲在LINQ表達式的屬性,像這樣

fields.Add("FirstName", new CellInfo 
        { 
         Title = "First Name", 
         FormatString = "Foo", 
         EvalExpression = p => p.FirstName 
        }); 

和使用過程中,一個人的對象以某種方式使用EvalExpression和獲得屬性值。我不知道從哪裏開始,或者有什麼樣的語法可以讓這樣的屬性可以評估。我很新的功能代表和表達式樹,我甚至不知道正確的關鍵字來搜索。希望我的描述很明確;如果沒有,請告訴我,我會在必要時提供詳情。 任何援助將不勝感激。

回答

1

你可以嘗試這樣的事情不必編寫的屬性名稱爲字符串,如果這是說強類型你的意思:

class CellInfo<T> 
{ 
    public string Title { get; set; } 
    public string FormatString { get; set; } 
    public Func<T, object> Selector { get; set; } 
} 

Dictionary<string, CellInfo<Person>> dict = new Dictionary<string, CellInfo<Person>>(); 

dict.Add("LastName", new CellInfo<Person> { Selector = p => p.LastName }); 
dict.Add("Age", new CellInfo<Person> { Selector = p => p.Age }); 

foreach (Person p in someCollection) 
{ 
    foreach (var cellInfo in dict) 
    { 
     object value = cellInfo.Value.Selector(p); 
    } 
} 
-1

(你的問題是明確的,但長。修剪初始的東西。)

這是ASP.NET MVC如何使用反射和lambda表達式用於在HTML輸入等創建字段名所以,你可以有一個看看這個問題的源代碼。

簡而言之,您必須將表達式轉換爲成員表達式並獲取名稱。簡單:

MemberExpression memberExpression = EvalExpression.Body as MemberExpression; 
if (memberExpression == null) 
    throw new InvalidOperationException("Not a memberExpression"); 

if (!(memberExpression.Member is PropertyInfo)) 
    throw new InvalidOperationException("Not a property"); 

return memberExpression.Member.Name; // returns FirstName 
+0

有人關心到c忽略爲什麼downvote? – Aliostad

+0

它可能是第一行的命令(而不是請求)。 – MikeKulls

0

我想代表是你需要的。事情是這樣的:

public delegate string EvalExpressionDelegate (Person); 

class CellInfo 
{ 
    public string Title {get; set;} 
    public string FormatString {get; set;} 
    public EvalExpressionDelegate EvalExpression = null; 
} 

fields.Add("FirstName", new CellInfo 
        { 
         Title = "First Name", 
         FormatString = "Foo", 
         EvalExpression = p => p.FirstName 
        }); 
+0

+1好信息。我猜'Func '是你所擁有的代表的簡寫,而有人沒有意識到這一點,並給你一個倒退。 –

+0

@ProfessorChaos我認爲downvote可能是因爲寫出委託被認爲是老式的做法,儘管它可以有其優點,如命名參數。 – MikeKulls

2

使用委託:

class CellInfo { 
    public string Title {get; set; } 
    public string FormatString {get; set; } 
    public Func<Person, object> EvalExpression { get; set; } 
} 

那麼你的拉姆達投入將工作...