首页 / 软件开发 / WCF / Enterprise Library深入解析与灵活应用(8):WCF与Exception Handling AppBl
Enterprise Library深入解析与灵活应用(8):WCF与Exception Handling AppBl2010-08-18 cnblogs ArtechEnterprise Library深入解析与灵活应用(8):WCF与Exception Handling AppBlock集成[下]在上篇中,我详细介绍了如何通过自定义ClientMessageInspector和 ErrorHandler,实现WCF与微软企业库中的Exception Handling Application Block(EHAB)之间的集成。这个方案的基本思路就是:当异常从服务端抛出,利 用EHAB针对某个配置好的异常处理策略进行处理;然后将处理有的异常通过 ServiceExceptionDetail对象进行封装,最后序列化置于Fault消息,最终被返回 给客户端;客户端接收到该Fault消息后,提取并创建ServiceExceptionDetail对 象,并通过反射重建异常;最后将异常抛出,使客户端可以根据客户端配置的异 常处理策略对该异常进行进一步的处理。为了实现WCF对 ServiceExceptionDetail对象的序列化和反序列化,我们必须通过 FaultContractAttribute特性将类型定义成错误契约,相应的形式如下面的代码 所示。在一般的情况下,如果你定义的服务是为他人所用,比如第三方服务消费 者,该错误契约的定义是必须的,因为相应的错误明细类型需要通过元数据的形 式发布出来,指导客户端如何对接收到的消息进行反序列化。但是,如果服务仅 供你自己的应用所用,那么你可以在运行时动态地添加相应的错误描述,从而避 免在服务契约的每一个服务操作方法上应用这么一个FaultContractAttribute。1: [ServiceContract(Namespace = "http://www.artech.com/")]
2: public interface ICalculator
3: {
4: [OperationContract]
5: [ExceptionHandlingBehavior ("myExceptionPolicy")]
6: [FaultContract(typeof (ServiceExceptionDetail), Action = "http://www.artech.com/fault")]
7: int Divide(int x, int y);
8: }
我们应用在操作方法上面的FaultContractAttribute特性,最终 会转换成操作描述(OperationDescription)的错误描述(FaultDescription) ,如果我们在运行时能够为所有的操作描述添加相应的错误描述,就能避免在每 个服务操作上面应用相同的FaultContractAttribute特性。不过,为了服务的重 用,我不介意这样偷懒,所以这种方案仅仅作为研究、学习之用。一、通 过自定义ServiceHost的方式动态添加错误描述(服务端)首先需要在服 务端为每一个服务操作添加基于ServiceExceptionDetail的错误描述,这可以通 过自定ServiceHost来实现。由于服务描述需要在ServiceHost开启之前生成方才 有效(具体的原因,相对比较复杂,大家可以在《WCF技术剖析(卷1)》第7章关于 服务寄宿的部分找到答案),所以我们将相关的逻辑定义在OnOpening方法之中。 在下面的代码中,我定义了这样一个简单的ServiceHost: ExceptionHandlingServiceHost。1: using System;
2: using System.ServiceModel;
3: using System.ServiceModel.Activation;
4: using System.ServiceModel.Description;
5:
6: namespace Artech.EnterLibIntegration.WcfExtensions
7: {
8: public class ExceptionHandlingServiceHost : ServiceHost
9: {
10: public ExceptionHandlingServiceHost(Type t, params Uri[] baseAddresses)
11: : base(t, baseAddresses)
12: { }
13:
14: protected override void OnOpening()
15: {
16: base.OnOpening();
17: foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
18: {
19: foreach (OperationDescription operation in endpoint.Contract.Operations)
20: {
21: FaultDescription faultDescription = new FaultDescription (ServiceExceptionDetail.FaultAction);
22: faultDescription.DetailType = typeof (ServiceExceptionDetail);
23: operation.Faults.Add(faultDescription);
24: }
25: }
26: }
27: }
28: }
逻辑相对比较简单:遍历所有终结点(ServiceEndpoint),为每 一个终结点的契约(ContractDescription)的每一个操作 (OperationDescription)添加错误明细类型为ServiceExceptionDetail的错误 描述(FaultDescription),并指定预定义的Action。对于自定义的 ServiceHost,可以直接用于不需要.svc文件进行访问的寄宿场景,也就是说对于 除了IIS和WAS的服务寄宿,可以直接采用自定义的ServiceHost。服务需要在基于 IIS和WAS的寄宿方式中采用自定义的ServiceHost,还需要为之创建相应的 ServiceHostFactory(关于ServiceHostFactory作用和用法,同样可以参阅《WCF 技术剖析(卷1)》第7章)。下面,我们为ExceptionHandlingServiceHost定义了 一个简单的ServiceHostFactory:ExceptionHandlingServiceHostFactory。1: using System;
2: using System.ServiceModel;
3: using System.ServiceModel.Activation;
4: using System.ServiceModel.Description;
5:
6: namespace Artech.EnterLibIntegration.WcfExtensions
7: {
8: public class ExceptionHandlingServiceHostFactory : ServiceHostFactory
9: {
10: protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
11: {
12: return new ExceptionHandlingServiceHost(serviceType, baseAddresses);
13: }
14: }
15: }