2017-05-10 268 views
0

泛型類的實例,我需要這樣的創建一個通用類的實例:創建動態泛型類型參數

Type T = Type.GetType(className).GetMethod(functionName).ReturnType; 
var comparer = new MyComparer<T>(); // ERROR: "The type or namespace name 'T' could not be found" 

我發現這個answer哪裏,這是可能僅與反思。但使用反射我得到的對象,我需要投給我的泛型類型。我試過像這樣

Type myGeneric = typeof(MyComparer<>); 
Type constructedClass = myGeneric.MakeGenericType(); 
object created = Activator.CreateInstance(constructedClass); 
var comparer = (T)Convert.ChangeType(created, T);// ERROR: "The type or namespace name 'T' could not be found" 

但是得到相同的錯誤。如何解決它?

下面是一個完整的例子:

public static bool Test(string className, string functionName, object[] parameters, object correctResult) 
    { 
     var method = Type.GetType(className).GetMethod(functionName); 
     Type T = method.ReturnType; 
     var myResult = method.Invoke(null, parameters); 
     dynamic myResultAsT = Convert.ChangeType(myResult, T); 
     dynamic correctResultAsT = Convert.ChangeType(correctResult, T); 
     var comparer = new MyComparer<T>(); // Problem is here!!!  
     return comparer.Equals(myResultAsT, correctResultAsT);    
    } 

的想法是做一個單元測試,它將調用帶有參數的功能,並將其結果與正確結果進行比較。但我需要自定義比較器,所以我實現MyComparer,由於編譯器錯誤,我無法使用它。

public class MyComparer<T> : IEqualityComparer<T> 
{ 
    public bool Equals(T x, T y){/* some implementation*/} 
} 
+0

你的錯誤信息沒有意義,你確定這是他們說的嗎? – DavidG

+0

@DavidG完整的編譯器錯誤是:'無法找到類型或名稱空間名稱'T'(缺少using指令還是程序集引用?)'。爲什麼它沒有意義? – Dejan

+1

然後你沒有顯示足夠的代碼,請顯示[mcve] – DavidG

回答

0

我覺得很簡單的解決問題。有沒有必要投object到特定類型的T,只是使用dynamic關鍵字,而不是鑄造

Type myGeneric = typeof(MyComparer<>); 
    Type constructedClass = myGeneric.MakeGenericType(T); 
    object created = Activator.CreateInstance(constructedClass); 
    dynamic comparer = created; // No need to cast created object to T 

,然後我可以用比較器通常調用它的方法,如:

return comparer.Equals(myResultAsT, correctResultAsT); 

LueTm評論,可能再次使用反射並調用比較器方法,但這種解決方案看起來更容易。

+0

這是更好的解決方案。 – LueTm

0

看起來你幾乎沒有:

// t is a variable, so make it lowercase. This is where some of the confusion comes from 
Type t = Type.GetType(className).GetMethod(functionName).ReturnType; 
Type myGeneric = typeof(IEqualityComparer<>); 

// You need to provide the generic type to make it generic with 
// You want IEqualityComparer<T>, so: 
Type constructedClass = myGeneric.MakeGenericType(t); 

// Now create the object 
object created = Activator.CreateInstance(constructedClass); 

// This is tricky without more context... 
// You could try this, but to tell you more I would need to know where you use 
// the comparer instance. Are you using it in a LINQ query, or in a Sort()? 
// If so just cast it to a IEqualityComparer<YourType>, and 
// make YourType whaterver you need it to be in the list or the query... 
var comparer = (IEqualityComparer<object>)created; 
+0

現在,它正在編譯,但它在運行時拋出InvalidCastException。 '無法投射類型爲'MyComparer1 [System.Double]'的對象以鍵入'MyComparer1 [System.Object]'。「我使用的是Myconnor,內含IEqualityComparer。 – Dejan

+0

我使用比較器實例僅用於具有兩個對象的'Equals'。我沒有在LINQ查詢中使用它。我在編輯的問題中編寫比較器的用法。 – Dejan

+0

只需用反射調用Equals方法,它就可以工作。如果您需要幫助,請寫信,我會編輯答案。 – LueTm