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