我有一个类,它将Generic Type作为初始化的一部分。
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();
这甚至可能吗?我似乎无法在网上找到答案。
答案 0 :(得分:33)
这部分的含义是:
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
)或继承自非通用基类(比如{{ 1}})定义他们需要的方法(这样你就可以将AnimalContext
转换为接口或非泛型基类)。另一种方法是使用a_context
。但同样,请记住,在执行此操作时,您有 none 泛型类型的好处。
答案 1 :(得分:9)
您可以使用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);
答案 2 :(得分:6)
您需要使用Reflection创建类型,然后调用该类型。类似的东西:
Animal a = MyFavoriteAnimal();
var contextType = typeof(EsbRepository<>).MakeGenericType(a.GetType());
dynamic context = Activator.CreateInstance(contextType);
context.DoAnimalStuff();
使用动态意味着将在运行时评估上下文变量,允许您调用DoAnimalStuff方法。