WCF服务代理的动态生成与使用

在日常的开发工作中,经常需要与WCF服务进行交互,主要是通过Web和MSMQ进行通信。经过一些初期的调整后,一切都运行得很顺利。通常情况下,这些服务都是在Windows到Web的通信环境中,可以控制客户端和服务器端的实现,因此有很多共享的类型。

然而,最近遇到一个快速增长的Web服务API,它遇到了元数据限制问题(显然,有最多30个方法的指导原则是有原因的!),这意味着无论是VS2008还是svcutil都无法可靠地生成可用的代理,除非改变每台可能需要生成代理的机器的标准配置。

经过一次大规模的重构,将一个服务拆分成了14个更小、更紧密的服务——这让面临一个更加巨大的任务:将这14个服务替换原来的一个服务。显然,这不会是一件容易的事,因为需要替换一个服务引用为14个!由于这个服务在几个项目中被使用,这可能会导致被钉在墙上。

在经过一番Google搜索、反射和检查生成的代码后,很快意识到,对于情况,根本不需要生成代理!因为所有的类型都是通过公共库在客户端和服务器之间共享的,而且WCF配置在配置文件中,可以直接使用ChannelFactory<>。这个聪明的类在WCF中做了所有的繁重工作,只需要服务合同接口和一个端点名称!

就像魔法一样,代理出现了...

using System; using System.ServiceModel; namespace MartinOnDotNet.Helpers.WCF { public class DynamicTidyProxy<TServiceContract> : IDisposable { public DynamicTidyProxy() { EndpointName = typeof(TServiceContract).Name; } public DynamicTidyProxy(string endpointConfigurationName) { EndpointName = endpointConfigurationName; } public string EndpointName { get; set; } private ChannelFactory<TServiceContract> _channel; private TServiceContract _client; public TServiceContract Client { get { if (_client == null) { if (!typeof(TServiceContract).IsInterface) throw new NotSupportedException("TServiceContract must be an interface!"); if (string.IsNullOrEmpty(EndpointName)) throw new NotSupportedException("EndpointName must be set prior to use!"); _channel = new ChannelFactory<TServiceContract>(EndpointName); _client = _channel.CreateChannel(); } return _client; } } public void Dispose() { if (_channel != null) { _channel.CloseConnection(); } GC.SuppressFinalize(this); } } }

已经将默认构造函数编码为使用服务合同接口的类型名称...所以请确保配置文件匹配!然后可以在代码中动态创建WCF代理

using (var proxy = new DynamicTidyProxy<IMagicComplexServiceContract>()) { proxy.Client.DoSomeMagicallyComplexOperation(); }

不需要svcutil或VS2008服务引用!这也意味着不必花费那么多时间进行重构!(至少今天不用...保证这会发生)。

public static void CloseConnection(this ICommunicationObject serviceClient) { if (serviceClient == null) return; try { if (serviceClient.State == CommunicationState.Opened) { serviceClient.Close(); } else { serviceClient.Abort(); } } catch (CommunicationException ex) { Logging.Logger.Log(ex); try { serviceClient.Abort(); } catch { } } catch (TimeoutException ex) { Logging.Logger.Log(ex); try { serviceClient.Abort(); } catch { } } catch (Exception ex) { Logging.Logger.Log(ex); try { serviceClient.Abort(); } catch { } throw; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485