动态创建模板的泛型类型

时间:2008-09-15 21:52:16

标签: c# generics

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

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

在我的情况下,我正在做路由,所以我不知道我的频道工厂将使用什么类型。我可以解析一个消息头来确定类型,但是我在那里碰到了一堵砖墙,因为即使我有一个Type I的实例也无法通过ChannelFactory期望泛型类型的实例。

用非常简单的术语重述这个问题的另一种方法是我试图做这样的事情:

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?

我可以在C#中使用这种方法吗?

3 个答案:

答案 0 :(得分:28)

您要找的是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);

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

答案 1 :(得分:8)

你应该看看Ayende的这篇文章:WCF, Mocking and IoC: Oh MY!。靠近底部的某个方法是一个名为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]);

答案 2 :(得分:4)

以下是一个问题:您确实需要在特定情况下创建具有确切合约类型的渠道吗?

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

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

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

如果您正在进行路由,通常情况下,处理通用通道形状(使用通用的全部服务合同)会更容易,并确保您发送的消息具有所有正确的标题和属性。