题
我正在使用 ChannelFactory 对 WCF 进行编程,它需要一个类型才能调用 CreateChannel 方法。例如:
IProxy proxy = ChannelFactory<IProxy>.CreateChannel(...);
就我而言,我正在进行路由,因此我不知道我的通道工厂将使用什么类型。我可以解析消息头来确定类型,但我遇到了障碍,因为即使我有 Type 的实例,我也无法将其传递给 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# 中利用?
解决方案
您正在寻找的是 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);
因此,您要做的是获取通用“模板”类的类型定义,然后使用运行时驱动类型构建该类型的专门化。
其他提示
你应该看看 Ayende 的这篇文章: WCF、模拟和 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]);
这里有一个问题:你 真的 需要根据您的具体情况创建具有确切合同类型的渠道吗?
由于您正在进行布线,因此您很有可能可以简单地处理通用通道形状。例如,如果您正在路由一条单向消息,那么您可以创建一个通道来发送消息,如下所示:
ChannelFactory<IOutputChannel> factory = new ChannelFactory<IOutputChannel>(binding, endpoint);
IOutputChannel channel = factory.CreateChannel();
...
channel.SendMessage(myRawMessage);
如果您需要发送到双向服务,只需使用 IRequestChannel 即可。
如果您正在进行路由,一般来说,处理通用通道形状(使用到外部的通用包罗万象的服务契约)并确保您发送的消息完全正确会容易得多标头和属性。
不隶属于 StackOverflow