从C#类型变量初始化通用变量

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

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

我现在能做的就是

 AnimalContext donkeyContext = new AnimalContext(); AnimalContext orcaContext = new AnimalContext(); 

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

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

这有可能吗? 我似乎无法在网上找到答案。

您对此部分的意思可能的:

 new AnimalContext(); 

显然,确切的语法是错误的,我们将会这样做,但是当你在运行时之前不知道类型参数 ,可以在运行时构造generics类型的实例。

你对这部分的意思不是

 AnimalContext a_Context 

也就是说,如果在编译时不知道类型参数,则无法将变量键入为generics类型。 generics是编译时构造,依赖于在编译时提供类型信息。 鉴于此,如果您在编译时不知道类型,则会失去generics的所有好处。

现在,要在运行时不知道类型的情况下在运行时构造generics类型的实例,您可以说:

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

请注意, a_context编译时类型是object 。 您必须将a_context转换为定义您需要访问的方法的类型或接口。 通常你会看到人们在这里做的是具有通用类型AnimalContext实现一些接口(比如IAnimalContext从非generics基类(比如说AnimalContext )inheritance,它定义了他们需要的方法(这样你就可以了a_context到接口或非generics基类)。 另一种选择是使用dynamic 。 但同样,请记住,在执行此操作时,您没有generics类型的任何好处。

您可以使用MakeGenericType方法使用generics类型的reflection,并使用dynamic关键字的优势:

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

所以你可以打电话:

 a_Context.DoAnimalStuff(); 

或者再次使用reflection来调用方法:

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

您需要使用Reflection创建类型,然后调用该类型。 就像是:

 Animal a = MyFavoriteAnimal(); var contextType = typeof(EsbRepository<>).MakeGenericType(a.GetType()); dynamic context = Activator.CreateInstance(contextType); context.DoAnimalStuff(); 

动态的使用意味着将在运行时评估上下文变量,允许您调用DoAnimalStuff方法。