创建 WCF ChannelFactory
我正在尝试将现有的 .NET Remoting 应用程序转换为 WCF。服务器和客户端共享公共接口,所有对象都是服务器激活的对象。
在 WCF 世界中,这类似于创建每次调用服务并使用 ChannelFactory
创建代理。我在如何为 ASP.NET 客户端正确创建 ChannelFactory
方面遇到了一些困难。
出于性能原因,我想缓存 ChannelFactory
对象,并在每次调用服务时创建通道。在 .NET 远程处理时代,曾经有 RemotingConfiguration.GetRegisteredWellknownClientTypes()
方法来获取客户端对象的集合,然后我可以缓存这些对象。看起来,在 WCF 世界中没有这样的东西,尽管我能够从配置文件中获取端点的集合。
现在我认为这会起作用。我可以创建这样的东西:
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() 方法的性能。
另一个小问题是我是否需要在 ASP.NET 应用程序结束后对通道工厂对象调用 ChannelFactory.Close()
方法,或者我可以让 .NET 框架自行处理通道工厂对象。使用 ((IChannel)proxy).Close()
方法调用服务方法后,代理通道将始终关闭。
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.
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.
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;
}
}
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.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是我用来处理通道工厂的帮助程序类:
然后我定义一个服务调用程序:
和一个实现:
现在每次需要调用 WCF 服务时,您都可以使用它:
这假设您已经为该服务定义了一个客户端端点配置文件中的
IMyServiceContract
服务契约:Here's a helper class that I use to handle channel factories:
Then I define a service invoker:
and an implementation:
Now every time you need to call a WCF service you could use this:
This assumes that you've defined a client endpoint for the
IMyServiceContract
service contract in the config file:是的,如果你想创建这样的东西 - 一个静态类来保存所有这些
ChannelFactory
实例 - 你绝对必须确保这个类是 100% 线程安全的,并且在访问时不会出错同时。我还没有太多使用 .NET 4 的功能,因此我无法具体评论这些功能 - 但我绝对建议使其尽可能安全。至于你的第二个(小)问题: ChannelFactory 本身是一个静态类 - 所以你不能真正调用它的
.Close()
方法。如果您想询问是否在实际的IChannel
上调用.Close()
方法,那么再次强调:是的,尽力成为一个好公民并关闭如果可以的话,请使用这些渠道。如果您错过了一个,.NET 会处理它 - 但不要只是将未使用的频道扔到地板上然后继续 - 自己清理! :-)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.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 actualIChannel
, 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! :-)我不喜欢这种调用结构:
而且你不能两次使用同一个通道。
我创建了这个解决方案:
现在您可以重复使用相同的通道,直到 using 语句调用 dispose。
GetChannel 方法基本上是一个 ChannelFactory.CreateChannel() 以及我正在使用的一些额外配置。
您可以像其他解决方案一样为 ChannelFactory 构建一些缓存。
连接类的代码:
I didn't like the calling construction:
Also you cannot use the same channel twice.
I've created this solution:
Now you can reuse the same channel until the using statement calls the dispose.
The GetChannel method is basicly a ChannelFactory.CreateChannel() with some extra config's I'm using.
You could build some caching for the ChannelFactory's as the other solutions does.
Code for the Connnection class:
@NelsonRothermel,是的,我走了这条路
不在 ChannelFactoryManager ChannelFaulted 事件处理程序中使用 try catch。
所以 ChannelFaulted 会变成
似乎允许原来的异常冒泡。
还选择不使用channel.close,因为它似乎会引发异常
因为通道已经处于故障状态。
FactoryFaulted 事件处理程序可能有类似的问题。
顺便说一句@Darin,很好的代码......
@NelsonRothermel, yes I went down the road of
not using a try catch in the ChannelFactoryManager ChannelFaulted event handler.
So ChannelFaulted would become
Seems to allow the original exception to bubble up.
Also chose not to use channel.close as it seems to throw an exception
as the channel is in a faulted state already.
FactoryFaulted event handler may have similar issues.
Btw @Darin, good bit of code...