我正在尝试将现有的.NET Remoting应用程序转换为WCF.服务器和客户端共享公共接口,所有对象都是服务器激活的对象.
在WCF世界中,这类似于创建每个呼叫服务和ChannelFactory<T>用于创建代理.我正在努力解决如何正确创建ChannelFactory<T>ASP.NET客户端的问题.
出于性能原因,我希望ChannelFactory<T>每次调用服务时都缓存对象并创建通道.在.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;
}
}
Run Code Online (Sandbox Code Playgroud)
我认为上面的代码可以工作,但我有点担心多个线程试图添加新ChannelFactory<T>对象,如果它不在查找中.由于我使用的是.NET 4.0,我首先考虑使用ConcurrentDictionary和使用GetOrAdd()方法或使用TryGetValue()方法来检查是否ChannelFactory<T>存在并且它不存在,然后使用GetOrAdd()方法.虽然ConcurrentDictionary.TryGetValue()和ConcurrentDictionary.GetOrAdd()方法不确定性能.
另一个小问题是我是否需要 …
我正在努力寻找实现WCF重试的最佳方法.我希望尽可能让客户体验尽可能干净.我知道有两种方法(见下文).我的问题是:" 我缺少第三种方法吗?也许是一种普遍接受的做法? "
方法#1:创建实现服务接口的代理.对于每次调用代理,请执行重试.
public class Proxy : ISomeWcfServiceInterface
{
public int Foo(int snurl)
{
return MakeWcfCall<int>(() => _channel.Foo(snurl));
}
public string Bar(string snuh)
{
return MakeWcfCall<string>(() => _channel.Bar(snuh));
}
private static T MakeWcfCall<T>(Func<T> func)
{
// Invoke the func and implement retries.
}
}
Run Code Online (Sandbox Code Playgroud)
方法#2:将MakeWcfCall()(上面)更改为public,并让消费代码直接发送func.
我不喜欢方法#1,每次接口更改时都必须更新Proxy类.
方法#2我不喜欢的是客户端必须将其调用包装在func中.
我错过了一个更好的方法吗?
编辑
我在这里发布了一个答案(见下文),基于接受的答案,指出了我正确的方向.我以为我会在答案中分享我的代码,以帮助某人完成我必须完成的工作.希望能帮助到你.
我想在WCF中注入我的接口的实现,但我想在WCF的客户端初始化我的容器的依赖注入.所以我可以为我的服务的每个客户端提供不同的实现.