2013-07-08 40 views
19

我有一个类需要一个通用类型作为其初始化的一部分。从一个C#类型变量初始化一个通用变量

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(); 

这甚至可能吗?我似乎无法找到这个在线的答案。

回答

20

你所说的这部分意味着可能是:

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

显然,准确的语法是错误的,我们会得到一点,但它可以构建一个通用的实例键入运行时间当您不知道类型参数时,直到运行时间

您通过这部分的意思是

AnimalContext<a.GetType()> a_Context 

也就是说,它是不可能一个变量的类型为泛型类型,如果你不知道编译时的类型参数。泛型是编译时间构造,并且依赖于在编译时可用的类型信息。鉴于此,如果在编译时不知道类型,则会失去泛型的所有好处。

现在,构建在运行时泛型类型,当你不知道的类型,直到运行时的一个实例,你可以说:

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

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

+3

回答的每个人都给出了比以前的答案提供了更多信息的答案。所有这些都是正确的,并且质量很好,但只有一个可以被选为答案,所以我选择了这个最具描述性的一个。我想感谢所有回答的人,并且我感谢所有的帮助(特别是在星期天晚上的晚些时候)。 –

+0

如果我的类不是泛型的,但是里面的方法是什么,我将如何使用MakeGenericType –

6

您可以通过使用MakeGenericType方法使用与普通的反射式,并采取dynamic关键字adavantage:

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

所以你可以拨打:

a_Context.DoAnimalStuff(); 

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

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

您需要创建类型usin g Reflection然后调用该类型。喜欢的东西:

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

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

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