2012-03-02 45 views
1

我一直在使用委託而不是反射來測試某些對象排序,並且它對字符串屬性有效,但如果我嘗試使用Int(或DateTime),它會失敗並且拋出嘗試訪問Int或DateTime屬性時,Open Delegate失敗

錯誤綁定到目標方法。

class Program 
{ 
    static void Main(string[] args) 
    { 
     var sample = new SampleClass() { Num = 13, Text = "Sample" }; 

     Console.WriteLine(ReadProp(sample,"Text")); //Works 
     Console.WriteLine(ReadProp(sample, "classProp")); //Works 
     Console.WriteLine(ReadProp(sample, "Num")); //Throws 'Error binding to target method.' 
    } 

    //Use a Delegate to improve speed of accessing property instead of reflection 
    static object ReadProp(SampleClass obj, string propName) 
    { 
     var method = obj.GetType().GetProperty(propName).GetGetMethod(); 
     var getForProp = (Func<SampleClass, object>)Delegate.CreateDelegate(typeof(Func<SampleClass, object>), null, method); 
     return getForProp(obj); 
    } 
} 

//A sample class for illustration purposes 
class SampleClass 
{ 
    public string Text { get; set; } 
    public int Num { get; set; } 
    public SampleClass classProp { get; set; } 
} 

我的問題是:爲什麼它的字符串或其他類而不是詮釋或日期時間工作?

我可以看到,如果我改變Func<SampleClass, object>Func<SampleClass, int>它就會爲我詮釋工作,但我希望對象將兩個工作。

回答

2

爲什麼它適用於字符串或其他類,但不適用於Int或DateTime?

因爲它返回一個int的方法沒有它返回一個object參考的方法。必須有一個拳擊轉換 - 所以一定要做到這一點,Delegate.CreateDelegate正試圖提供一個代表只是調用委託並返回結果,沒有值轉換涉及。

這是輕微的疼痛做,但基本上我懷疑你應該要麼來建設有一個適當的返回值的Func,並使用直接你應該通過包裝委託其所謂的「真正」的代表去裝箱結果。

(請注意,在你的示例代碼,你每次都創建委託,這將是不超過反射快。希望你真正的代碼是比較明智​​的:)

如果你看看你this code from protobuf-csharp-port會看到我有一個方法來做到這一點 - 一個lambda表達式調用強類型的委託,然後使用隱式轉換爲object(必要時進行裝箱)以提供值。你應該能夠使用非常相似的東西。但是,如果你正在排序,你真的 a Func<T, object>?如果您使用強類型的委託,您可能可以避免所有這些拳擊。

+0

是的,我真正的代碼只創建一次委託 – deepee1 2012-03-02 21:03:40

+0

感謝您的鏈接,我會看看。在我的情況下,我不知道設計時的返回類型,並且必須在運行時確定屬性返回類型 – deepee1 2012-03-02 21:08:32

+0

@ deepee1:鏈接中的代碼就是這樣 - 你給它一個'MethodInfo',它給你一個'Func '。通用方法在創建委託時通過反射調用。 – 2012-03-02 21:13:03

相關問題