从 C # 类型变量初始化泛型变量

我有一个类,它将 GenericType 作为其初始化的一部分。

public class AnimalContext<T>
{
public DoAnimalStuff()
{
//AnimalType Specific Code
}
}

我现在能做的就是

AnimalContext<Donkey> donkeyContext = new AnimalContext<Donkey>();
AnimalContext<Orca> orcaContext = new AnimalContext<Orca>();

但是我需要/想要做的是能够声明一个 AnimalContext 初始化为一个只在运行时才知道的类型。比如说,

Animal a = MyFavoriteAnimal(); //returns an instance of a class
//implementing an animal
AnimalContext<a.GetType()> a_Context = new AnimalContext<a.GetType()>();
a_Context.DoAnimalStuff();

这可能吗? 我在网上找不到答案。

96856 次浏览

通过使用 MakeGenericType方法,您可以使用泛型类型的反射,并利用 dynamic关键字:

var type = typeof (AnimalContext<>).MakeGenericType(a.GetType());
dynamic a_Context = Activator.CreateInstance(type);

所以你可以打电话:

a_Context.DoAnimalStuff();

或者再次使用反射调用方法:

type.GetMethod("DoAnimalStuff").Invoke(a_Context, null);

您需要使用反射创建类型,然后调用该类型,比如:

Animal a = MyFavoriteAnimal();
var contextType = typeof(EsbRepository<>).MakeGenericType(a.GetType());


dynamic context = Activator.CreateInstance(contextType);
context.DoAnimalStuff();

使用动态意味着将在运行时计算上下文变量,从而允许您调用 DoAnimalStuff 方法。

你所说的 可能是什么意思:

new AnimalContext<a.GetType()>();

显然,确切的语法是错误的,我们将讨论这个问题,但是当您直到 运行时间才知道类型参数时,可以在 运行时间构造泛型类型的实例。

你说的这部分是指 没有:

AnimalContext<a.GetType()> a_Context

也就是说,如果您不知道 编译时处的类型参数,就不可能将变量类型化为泛型类型。泛型是 编译时构造,依赖于在 编译时中具有可用的类型信息。因此,如果在编译时不知道泛型的类型,就会失去泛型的所有好处。

现在,要在运行时构造一个泛型类型的实例,如果直到运行时才知道该类型,可以说:

var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);

请注意,a_context编译时类型是 object。您必须将 a_context强制转换为定义需要访问的方法的类型或接口。通常你会看到人们在这里做的是使泛型类型 AnimalContext<T>实现一些接口(比如说 IAnimalContext) 或者从非泛型基类(比如说 AnimalContext)继承,定义他们需要的方法(这样你就可以将 a_context强制转换为接口或非泛型基类)。另一种选择是使用 dynamic。但是,请记住,这样做有泛型类型的好处 object0。