问题描述
我正在尝试将现有的 .NET Remoting 应用程序转换为 WCF.服务器和客户端共享公共接口,所有对象都是服务器激活的对象.
I'm trying to convert an existing .NET Remoting application to WCF. Both server and client share common interface and all objects are server-activated objects.
在 WCF 世界中,这类似于创建按调用服务并使用 ChannelFactory
创建代理.我在如何为 ASP.NET 客户端正确创建 ChannelFactory
方面遇到了一些困难.
In WCF world, this would be similar to creating per-call service and using ChannelFactory<T>
to create a proxy. I'm struggling a bit with how to properly create ChannelFactory<T>
for an ASP.NET client.
出于性能原因,我想缓存 ChannelFactory
对象,并在每次调用服务时创建频道.在 .NET 远程处理时代,曾经有 RemotingConfiguration.GetRegisteredWellknownClientTypes()
方法来获取我可以缓存的客户端对象集合.看来,在 WCF 世界中没有这样的事情,尽管我能够从配置文件中获取端点集合.
For performance reasons, I want to cache ChannelFactory<T>
objects and just create channel every time I call the service. In .NET remoting days, there used to be RemotingConfiguration.GetRegisteredWellknownClientTypes()
method to get a collection of client objects that I could then cache. It appears, in WCF world there is no such thing, although I was able to get a collection of endpoints from config file.
现在这是我认为可行的方法.我可以创建这样的东西:
Now here is what I think will work. I can create something like this:
public static ProxyHelper
{
static Dictionary<Type, object> lookup = new Dictionary<string, object>();
static public T GetChannel<T>()
{
Type type = typeof(T);
ChannelFactory<T> factory;
if (!lookup.ContainsKey(type))
{
factory = new ChannelFactory<T>();
lookup.Add(type, factory);
}
else
{
factory = (ChannelFactory<T>)lookup[type];
}
T proxy = factory.CreateChannel();
((IClientChannel)proxy).Open();
return proxy;
}
}
我认为上面的代码可以工作,但我有点担心多个线程试图添加新的 ChannelFactory
对象,如果它不在查找中.由于我使用的是 .NET 4.0,我在考虑使用 ConcurrentDictionary
并使用 GetOrAdd()
方法或首先使用 TryGetValue()
方法检查 ChannelFactory
是否存在和不存在,然后使用 GetOrAdd()
方法.不确定 ConcurrentDictionary.TryGetValue()
和 ConcurrentDictionary.GetOrAdd()
方法的性能.
I think the above code will work, but I'm a bit worried about multiple threads trying to add new ChannelFactory<T>
objects if it's not in the lookup. Since I'm using .NET 4.0, I was thinking about using ConcurrentDictionary
and use GetOrAdd()
method or use TryGetValue()
method first to check if ChannelFactory<T>
exists and it does not exist, then use GetOrAdd()
method. Not sure about performance though of ConcurrentDictionary.TryGetValue()
and ConcurrentDictionary.GetOrAdd()
method.
另一个小问题是我是否需要在 ASP.NET 应用程序结束后对通道工厂对象调用 ChannelFactory.Close()
方法,或者我可以让 .NET 框架在其上处理通道工厂对象自己的.使用 ((IChannel)proxy).Close()
方法调用服务方法后,代理通道将始终关闭.
Another minor question is whether I need to call ChannelFactory.Close()
method on channel factory objects after ASP.NET application ends or can I just let .NET framework dispose the channel factory objects on its own. The proxy channel will always be closed after calling service method by using ((IChannel)proxy).Close()
method.
推荐答案
是的,如果你想创建这样的东西 - 一个静态类来保存所有那些 ChannelFactory
实例 - 你肯定必须确保此类是 100% 线程安全的,并且在并发访问时不会出错.我还没有经常使用 .NET 4 的功能,所以我不能具体评论这些 - 但我肯定会建议尽可能安全.
Yes, if you want to create something like this - a static class to hold all those ChannelFactory<T>
instances - you definitely have to make sure this class is 100% thread-safe and cannot stumble when accessed concurrently. I haven't used .NET 4's features much yet, so I cannot comment on those specifically - but I would definitely recommend to make this as safe as possible.
至于你的第二个(次要)问题:ChannelFactory 本身是一个静态类 - 所以你不能真正调用它的 .Close()
方法.如果您想询问是否要在实际的 IChannel
上调用 .Close()
方法,那么再说一遍:是的,尽最大努力成为一个好公民并关闭如果可以的话,这些频道.如果您错过了一个,.NET 会处理它 - 但不要只是将您未使用的频道扔在地板上然后继续 - 自己清理!:-)
As for your second (minor) question: the ChannelFactory itself is a static class - so you cannot really call a .Close()
method on it. If you meant to ask whether or not to call the .Close()
method on the actual IChannel
, then again: yes, try your best to be a good citizen and close those channels if you ever can. If you miss one, .NET will take care of it - but don't just toss your unused channels on the floor and go on - clean up after yourself! :-)
这篇关于创建 WCF ChannelFactory<T>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!