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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17519078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:42:59  来源:igfitidea点击:

Initializing a Generic variable from a C# Type Variable

c#generics

提问by Peter Lange

I have a class that takes a Generic Type as part of its initialization.

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

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

What I can do right now is

我现在能做的是

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

But what I need/want to do is be able to declare an AnimalContext initialized to a type that is only known at runtime. For instance,

但是我需要/想要做的是能够声明一个 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();

Is this even possible? I can't seem to find an answer for this online.

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

采纳答案by jason

What you mean by this part ispossible:

这部分的意思可能的:

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

Obviously that exact syntax is wrong, and we'll get to that, but it ispossible to construct an instance of a generic type at runtimewhen you don't know the type parameters until runtime.

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

What you mean by this part is not:

这部分的意思不是

AnimalContext<a.GetType()> a_Context

That is, it is impossible to type a variable as a generic type if you don't know the type parameters at compile-time. Generics are compile-timeconstructs, and rely on having the type information available at compile-time. Given this, you lose all the benefits of generics if you don't know the types at compile-time.

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

Now, to construct an instance of a generic type at runtime when you don't know the type until runtime, you can say:

现在,当您直到运行时才知道类型时,要在运行时构造泛型类型的实例,您可以说:

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

Note that the compile-timetype of a_contextis object. You will have to cast a_contextto a type or interface that defines the methods you need to access. Often what you'll see people do here is have the generic type AnimalContext<T>implement some interface (say IAnimalContext) orinherit from a non-generic base class (say AnimalContext) that defines the methods they need (so then you can cast a_contextto the interface or the non-generic base class). Another alternative is to use dynamic. But again, keep in mind, you have noneof the benefits of generic types in doing this.

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

回答by cuongle

You can use reflection with generic type by using MakeGenericTypemethod and take adavantage of dynamickeyword:

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

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

So you can call:

所以你可以调用:

a_Context.DoAnimalStuff();

Or use reflection again to call method:

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

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

回答by SCB

You would need to create the type using Reflection and then invoke that type. Something like:

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

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

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

The use of dynamic means that the context variable will be evaluated at run time allowing for you to call the DoAnimalStuff method.

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