zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Enterprise Library深入解析与灵活应用(8):WCF与Exception Handling AppBlock集成[下]

WCFWCF集成应用 解析 深入 灵活 library
2023-09-27 14:27:57 时间

上篇中,我详细介绍了如何通过自定义ClientMessageInspector和ErrorHandler,实现WCF与微软企业库中的Exception Handling Application Block(EHAB)之间的集成。这个方案的基本思路就是:当异常从服务端抛出,利用EHAB针对某个配置好的异常处理策略进行处理;然后将处理有的异常通过ServiceExceptionDetail对象进行封装,最后序列化置于Fault消息,最终被返回给客户端;客户端接收到该Fault消息后,提取并创建ServiceExceptionDetail对象,并通过反射重建异常;最后将异常抛出,使客户端可以根据客户端配置的异常处理策略对该异常进行进一步的处理。(Source Code从这里下载)

为了实现WCF对ServiceExceptionDetail对象的序列化和反序列化,我们必须通过FaultContractAttribute特性将类型定义成错误契约,相应的形式如下面的代码所示。在一般的情况下,如果你定义的服务是为他人所用,比如第三方服务消费者,该错误契约的定义是必须的,因为相应的错误明细类型需要通过元数据的形式发布出来,指导客户端如何对接收到的消息进行反序列化。但是,如果服务仅供你自己的应用所用,那么你可以在运行时动态地添加相应的错误描述,从而避免在服务契约的每一个服务操作方法上应用这么一个FaultContractAttribute

 1: [ServiceContract(Namespace = "http://www.artech.com/")]

我们应用在操作方法上面的FaultContractAttribute特性,最终会转换成操作描述(OperationDescription)的错误描述(FaultDescription),如果我们在运行时能够为所有的操作描述添加相应的错误描述,就能避免在每个服务操作上面应用相同的FaultContractAttribute特性。不过,为了服务的重用,我不介意这样偷懒,所以这种方案仅仅作为研究、学习之用。

一、通过自定义ServiceHost的方式动态添加错误描述(服务端)

首先需要在服务端为每一个服务操作添加基于ServiceExceptionDetail的错误描述,这可以通过自定ServiceHost来实现。由于服务描述需要在ServiceHost开启之前生成方才有效(具体的原因,相对比较复杂,大家可以在《WCF技术剖析(卷1)》第7章关于服务寄宿的部分找到答案),所以我们将相关的逻辑定义在OnOpening方法之中。在下面的代码中,我定义了这样一个简单的ServiceHost:ExceptionHandlingServiceHost。


 10: public ExceptionHandlingServiceHost(Type t, params Uri[] baseAddresses)

 19: foreach (OperationDescription operation in endpoint.Contract.Operations)

 21: FaultDescription faultDescription = new FaultDescription(ServiceExceptionDetail.FaultAction);

 10: protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)

二、通过自定义ChannelFactory TChanel 的方式动态添加错误描述(客户端)

服务端需要为每一个操作添加基于ServiceExceptionDetail的错误描述,以便实现对该对象的序列化;同理,客户端同样需要这样一个错误描述,以实现对该对象的反序列化。我们可以将这样的功能通过一个自定义ChannelFactory TChannel 来实现。下面定义的ExceptionHandlingChannelFactory就是这样一个自定的ChannelFactory TChannel 。对错误描述的添加实现在重写的CreateDescription方法中:


 6: public class ExceptionHandlingChannelFactory TChannel :ChannelFactory TChannel 

 8: public ExceptionHandlingChannelFactory(string endpointConfigurationName)

 15: foreach (OperationDescription operation in serviceEndpoint.Contract.Operations)

 17: FaultDescription faultDescription = new FaultDescription(ServiceExceptionDetail.FaultAction);

三、实例演示

那么,对其我们给出的例子,我们就要使用我们上面创建的这两个组件了。首先,有了这两个组件的帮助,在服务契约中,我们再也不需要在繁琐地为每一个服务操作定义相同的FaultContractAttribute特性了。于是我们先将其拿掉。


然后,再进行服务寄宿的时候,直接利用我们定义的ExceptionHandlingServiceHost就可以了。


 10: using (ExceptionHandlingServiceHost host = new ExceptionHandlingServiceHost(typeof(CalculatorService)))

而客户端,我们可以借助于我们定义的ExceptionHandlingChannelFactory TChannel 实现对服务代理的创建。


 10: using (ExceptionHandlingChannelFactory ICalculator channelFactory = new ExceptionHandlingChannelFactory ICalculator (

微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 原文链接

《Visual Edge Computing Service视图计算产品发布介绍》PDF 立即下载