2012-05-03 31 views
2

讓我們考慮一個接口的方法:調用與在編譯時已知不同類型的循環泛型方法

public Interface IA { 
    T[] Get<T>() where T : IB; 
} 

在另一個地方,我想調用此方法N次n種這是已知編譯時間。以下代碼示意我的意圖。現在

foreach(Type t in new Type[] { typeof(X), typeof(Y), typeof(Z) }) 
{ 
    InterfaceXYZImplement[] arr = c.Resolve<IA>().Get<t>(); 
    //...more here 
} 

,該的foreach循環顯然使類型成爲一個運行時間值,所以我將不得不使用MakeGenericMethod

有沒有辦法以這樣的方式編寫代碼,以便我可以爲X,Y和Z執行代碼,但只調用一次寫入的方法?

在方法中包裝代碼只會將問題向上移動(這是一個部分解決方案,但不是最終解決方案,嘿)。

在此先感謝
Tymek

+0

多大'N'? – LukeH

+2

爲什麼不直接給他們打電話?編譯時已知的類型每次都在變化? – leppie

+0

我並不清楚「調用只寫一次的方法」是什麼意思,並且[@mrtofigh的解決方案](http://stackoverflow.com/a/10429266)有什麼問題 - 你能否詳細說明一下?使用'MakeGenericMethod'有什麼問題? – AakashM

回答

1

你可以使用一些輔助方法,使相當多的假設,並使用.NET4新dynamic關鍵字實現這一目標。

基本上,溶液利用了DLR的特徵的正確推斷要用於一個通用方法的類型,當使用該類型的參數是一個dynamic。對於這個工作,你將需要兩個輔助方法:

IB[] Get(IA a, Type t) 
{ 
    dynamic dummy = Activator.CreateInstance(t); 
    return Get(a, dummy); 
} 

T[] Get<T>(IA a, T dummy) where T : IB 
{ 
    return a.Get<T>(); 
} 

而且你的代碼會調用第一個的一些輔助方法:

foreach(var t in new Type[] { typeof(X), typeof(Y), typeof(Z) }) 
{ 
    IB[] arr = Get(c.Resolve<IA>(), t); 
    // do more stuff here 
} 

正如你所看到的,這種方法有幾個抽獎背上:

  1. 對於循環中的每種類型,通過Activator.CreateInstance(t)創建一個新實例。這條線假設存在一個可以使用的公共無參數構造函數,並且這個構造函數不會做任何重要的事情。
  2. 如果循環中的任何類型未實現IB,則此代碼將在運行時引發異常。將不會有編譯錯誤。
  3. 結果總是一個IB實例的數組,而不是特定類型的數組。
+0

@mrtofigh:不,那不可能。再看一遍。 –

1

定義的擴展方法:

public static class Extensions 
{ 
    public static void Get<T>(this IA a, Action<T[]> action, params Type[] types) where T : IB 
    { 
     foreach (var type in types) 
     { 
      var method = a.GetType().GetMethod("Get").MakeGenericMethod(type); 
      var ts = (T[])method.Invoke(a, null); 
      action(ts); 
     } 
    } 
} 

用途:

a.Get(arr => { 
    // work on result 
}, typeof(X), typeof(Y), typeof(Z)); 
+1

一個OP提到他不想走這條路...... – leppie

+0

魔法繩子! Aaaaaah!鑄件! AAAAH! – mayu

相關問題