2010-10-21 40 views
5

我們有一些代碼給出了屬性名稱使用反射來實現比較器。給定一個屬性名稱,我如何創建一個委託來獲得它的值

我想存儲委託/ Func來獲取價值,而不是每次我們需要獲得價值時支付反映價格。

鑑於一類是這樣的:

public class Person 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 
} 

我試着寫這將創建一個委託我

Func<T, object> CreateGetFuncFor<T>(string propertyName) 
{ 
    PropertyInfo prop = typeof(T).GetProperty(propertyName); 

    return (Func<T, object>)Delegate.CreateDelegate(typeof(Func<T, object>), 
                null, 
                prop.GetGetMethod()); 
} 

功能下面的代碼工作正常,爲獲取名稱

var person = new Person { Name = "Dave", Age = 42 }; 

var funcitonToGetName = CreateGetFuncFor<Person>("Name"); 
Console.WriteLine(funcitonToGetName(person)); 

var functionToGetAge = CreateGetFuncFor<Person>("Age"); 

但對於Age proerty,它會拋出一個ArgumentException,並顯示消息「Error binding to targ et方法「

我錯過了什麼?還有另一種方法可以做到嗎?

+0

感謝兩位盧克! – Argos 2010-10-21 16:23:41

回答

8

這似乎很奇怪,你知道在編譯時的聲明類型而不是屬性類型。無論如何...

您需要額外的步驟將屬性值轉換爲object,以便它與Func<T,object>委託人的返回類型相匹配。 (對於參考類型的屬性,額外的步驟不是嚴格必要的,但不會造成任何傷害。)

Func<T, object> CreateGetFuncFor<T>(string propertyName) 
{ 
    var parameter = Expression.Parameter(typeof(T), "obj"); 
    var property = Expression.Property(parameter, propertyName); 
    var convert = Expression.Convert(property, typeof(object)); 
    var lambda = Expression.Lambda(typeof(Func<T, object>), convert, parameter); 

    return (Func<T, object>)lambda.Compile(); 
} 
+0

哦,我同意 - 但我目前無法更改代碼的這些部分。 – Argos 2010-10-21 16:22:40

1

它可能是因爲年齡基本上定義爲:

public int Age {get; private set;} 

並返回int不隱式轉換爲返回一個object的方法等,而String是。

嘗試:

Func<T, R> CreateGetFuncFor<T, R>(string propertyName) 
{ 
    PropertyInfo prop = typeof(T).GetProperty(propertyName); 
    return (Func<T, R>)Delegate.CreateDelegate(typeof(Func<T, R>), 
                null, 
                prop.GetGetMethod()); 
} 

然後

var functionToGetAge = CreateGetFuncFor<Person, int>("Age"); 
+0

不幸的是,在我想使用它的代碼中,我不知道propery是什麼類型。 – Argos 2010-10-21 15:28:29

+0

如果你不知道類型,你打算怎麼處理Age?你能稍微擴展你的用例嗎? – luke 2010-10-21 15:48:04

+0

最終在調用System.Collections.Comparer.Default.Compare時使用的值 – Argos 2010-10-21 16:03:06

相關問題