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