这真的让我今天难过.我确定它很简单,但是......这是我的示例代码:
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 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创建了一个新的Type实例.
现在,如果我将创建的实例传递给采用泛型参数的函数,则泛型类型总是作为Object出现,因为Activator.CreateInstance()返回一个Object,因此"var x"是一个Object,在这种情况下,不是一个ArrayList.
我需要发生的是泛型类型是实际类型,在他的情况下是"ArrayList".
我知道有一个我可以使用的Activator.CreateInstance(),但我不能在该方法的尖括号内使用Type(PropertyInfo.PropertyType).
我也可以只是转换返回的对象,如:
myPropType x = (myPropType)Activator.CreateInstance(myPropType);
但很明显,这不会编译...另外它无论如何都不会有效,因为演员是编译时间,我不知道直到运行时的类型,但从概念上讲它是我需要的......
所以我坚持使用这个Type,但我无法弄清楚如何将它传递给WhatAmI()方法,并且让T为ArrayList,而不是Object.
想法?
要Type
在运行时调用泛型方法,您需要使用反射 - MakeGenericMethod
尤其是:
typeof(Program).GetMethod("WhatAmI", BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(x.GetType()).Invoke(null, new object[] { x });
否则,编译器会
从变量类型中推断出- object
在这种情况下.
这里的一个侧面是你可以通过只进行一次反射来改进事物- 即不使用Activator
,而是使用通用约束:
private static void WhatAmI() 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);
仅使用类型调用方法 - 在方法内创建实例.这通常比重复反射更快.