2009-01-07 75 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