2009-01-07 59 views
1

今天真的讓我難堪。我敢肯定它的簡單,但...這是我的示例代碼:.NET泛型:使用Activator創建類型作爲泛型顯示錯誤類型?需要解決方法

using System; 
using System.Collections; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     public ArrayList SomeProp { get; set; } 

     static void Main(string[] args) 
     { 
      // Get the Type of a property by reflection. 
      Type myPropType = typeof(Program).GetProperty("SomeProp").PropertyType; 

      // Create an instance of the determined Type. 
      var x = Activator.CreateInstance(myPropType); 

      // Now try to use that instance, passing to a method that takes a generic. 
      WhatAmI(x); 

      Console.ReadKey(); 
     } 

     private static void WhatAmI<T>(T x) 
     { 
      Console.WriteLine("T is: " + typeof(T).FullName); 
      Console.WriteLine("x is: " + x.GetType().FullName); 
     } 
    } 
} 

這裏的輸出是:

T is: System.Object 
x is: System.Collections.ArrayList 

基本上是怎麼回事上我有一些類中的一些屬性。它來自哪裏/哪裏並不重要。重要的部分是我得到該屬性的PropertyInfo。從那裏我創建了一個類型與激活器的新實例。

現在,如果我將創建的實例傳遞給接受泛型參數的函數,泛型類型總是以對象的形式出現,因爲Activator.CreateInstance()返回一個Object,所以「var x」是一個Object,在這種情況下,ArrayList。

我需要發生的是泛型類型是實際類型,int他的情況「ArrayList」。

我知道有一個Activator.CreateInstance()可以用來代替,但我不能在該方法的尖括號中使用Type(PropertyInfo.PropertyType)。

我也只投返回的對象,如:

myPropType x = (myPropType)Activator.CreateInstance(myPropType); 

但顯然無法編譯...加上它不會是有效的,也因爲演員陣容編譯時間,我不直到運行時才知道類型,但在概念上它是我需要的...

所以我堅持這種類型,但我無法弄清楚如何讓它傳遞給WhatAmI()方法,並有T是ArrayList,而不是對象。

想法?

回答

7

要調用在運行時使用Type通用的方法,你需要使用反射 - 特別是MakeGenericMethod,是這樣的:

typeof(Program).GetMethod("WhatAmI", 
    BindingFlags.Static | BindingFlags.NonPublic) 
    .MakeGenericMethod(x.GetType()).Invoke(null, new object[] { x }); 

否則,編譯器推斷<T>從變量類型 - 本object案件。

一面這裏的一點是,你可以只是做反射一次改善的事情 - 即不使用Activator,而是改用通用約束:

private static void WhatAmI<T>() where T : new() 
    { 
     T x = new T(); 
     Console.WriteLine("T is: " + typeof(T).FullName); 
     Console.WriteLine("x is: " + x.GetType().FullName); 
    } 

定義方法沒有一個arg,但是有一個默認的構造函數;然後:

// Get the Type of a property by reflection. 
    Type myPropType = typeof(Program).GetProperty("SomeProp").PropertyType; 

    // Now call a generic method just using the type 
    typeof(Program).GetMethod("WhatAmI", 
     BindingFlags.Static | BindingFlags.NonPublic) 
      .MakeGenericMethod(myPropType).Invoke(null, null); 

要求僅僅使用類型的方法 - 實例被創建的方法。這通常比反覆反射更快。

+0

Fortuantely我需要應用這個地方,這是我自己的方法,我知道是通用的,所以這應該工作。我可以看到這對共享庫來說是一個真正的問題,你可能會不經意地調用一個你不知道的方法是通用的。無論如何,我會給這個鏡頭。謝謝! – CodingWithSpike 2009-01-07 16:31:16