从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方法。