C# 为模板动态创建泛型类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/67370/
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-03 11:03:55  来源:igfitidea点击:

Dynamically Create a generic type for template

提问by t3rse

I'm programming WCF using the ChannelFactory which expects a type in order to call the CreateChannel method. For example:

我正在使用 ChannelFactory 编程 WCF,它需要一个类型来调用 CreateChannel 方法。例如:

IProxy proxy = ChannelFactory<IProxy>.CreateChannel(...);

In my case I'm doing routing so I don't know what type my channel factory will be using. I can parse a message header to determine the type but I hit a brick wall there because even if I have an instance of Type I can't pass that where ChannelFactory expects a generic type.

就我而言,我正在做路由,所以我不知道我的通道工厂将使用什么类型。我可以解析消息头来确定类型,但我在那里碰到了砖墙,因为即使我有一个 Type 实例,我也无法传递 ChannelFactory 需要泛型类型的地方。

Another way of restating this problem in very simple terms would be that I'm attempting to do something like this:

用非常简单的术语重申这个问题的另一种方法是,我正在尝试做这样的事情:

string listtype = Console.ReadLine(); // say "System.Int32"
Type t = Type.GetType( listtype);
List<t> myIntegers = new List<>(); // does not compile, expects a "type"
List<typeof(t)> myIntegers = new List<typeof(t)>(); // interesting - type must resolve at compile time?

Is there an approach to this I can leverage within C#?

有没有我可以在 C# 中利用的方法?

采纳答案by IDisposable

What you are looking for is MakeGenericType

您正在寻找的是 MakeGenericType

string elementTypeName = Console.ReadLine();
Type elementType = Type.GetType(elementTypeName);
Type[] types = new Type[] { elementType };

Type listType = typeof(List<>);
Type genericType = listType.MakeGenericType(types);
IProxy  proxy = (IProxy)Activator.CreateInstance(genericType);

So what you are doing is getting the type-definition of the generic "template" class, then building a specialization of the type using your runtime-driving types.

因此,您正在做的是获取通用“模板”类的类型定义,然后使用运行时驱动类型构建该类型的特化。

回答by tomasr

Here's a question: Do you reallyneed to create a channel with the exact contract type in your specific case?

这里有一个问题:在您的特定情况下,您真的需要创建一个具有确切合同类型的渠道吗?

Since you're doing routing, there's a very good chance you could simply deal with the generic channel shapes. For example, if you're routing a one-way only message, then you could create a channel to send the message out like this:

由于您正在进行布线,因此您很有可能可以简单地处理通用通道形状。例如,如果您正在路由一条单向消息,那么您可以创建一个通道来发送消息,如下所示:

ChannelFactory<IOutputChannel> factory = new ChannelFactory<IOutputChannel>(binding, endpoint);
IOutputChannel channel = factory.CreateChannel();
...
channel.SendMessage(myRawMessage);

If you needed to send to a two-way service, just use IRequestChannel instead.

如果您需要发送到双向服务,请改用 IRequestChannel。

If you're doing routing, it is, in general, a lot easier to just deal with generic channel shapes (with a generic catch-all service contract to the outside) and just make sure the message you're sending has all the right headers and properties.

如果你在做路由,一般来说,处理通用的通道形状(使用通用的包罗万象的服务合同到​​外部)要容易得多,只需确保你发送的消息是正确的标题和属性。

回答by Bill

You should look at this post from Ayende: WCF, Mocking and IoC: Oh MY!. Somewhere near the bottom is a method called GetCreationDelegate which should help. It basically does this:

你应该看看 Ayende 的这篇文章:WCF、Mocking 和 IoC:我的天哪!. 靠近底部的地方是一个名为 GetCreationDelegate 的方法,它应该会有所帮助。它基本上是这样做的:

string typeName = ...;
Type proxyType = Type.GetType(typeName);

Type type = typeof (ChannelFactory<>).MakeGenericType(proxyType);

object target = Activator.CreateInstance(type);

MethodInfo methodInfo = type.GetMethod("CreateChannel", new Type[] {});

return methodInfo.Invoke(target, new object[0]);