我需要记录WCF服务中的每个方法调用,并抛出任何异常.这导致了很多冗余代码,因为每个方法都需要包括类似于以下的样板:
[OperationContract] public ResultBase<int> Add(int x,int y) { var parameters = new object[] { x,y } MyInfrastructure.LogStart("Add",parameters); try { // actual method body goes here } catch (Exception ex) { MyInfrastructure.LogError("Add",parameters,ex); return new ResultBase<int>("Oops,the request Failed",ex); } MyInfrastructure.LogEnd("Add",parameters); }
有没有办法我将所有这些逻辑封装到一个属性MyServiceLoggingBehaviorAttribute中,我可以这样应用到服务类(或方法):
[ServiceContract] [MyServiceLoggingBehavior] public class MyService { }
注1
我意识到这可以使用Aspect-oriented programming,但在C#中,唯一的方法是修改字节码,这需要使用像PostSharp这样的第三方产品.我想避免使用商业图书馆.
笔记2
请注意,Silverlight应用程序是服务的主要消费者.
注3#
在某些情况下,WCF trace logging是一个很好的选择,但是在这里不起作用,因为如上所述,我需要检查,并且在异常更改的情况下返回值.
解决方法
是的,可以使用
extensibility points built into WCF封装这种日志记录.实际上有多种可能的方法.我在这里描述的一个添加了一个IServiceBehavior,它使用一个自定义的
IOperationInvoker
,并且不需要任何web.config修改.
这有三个部分.
>创建一个IOperationInvoker的实现,它将方法调用包含在所需的日志记录和错误处理中.
>创建应用步骤1的调用者的IOperationBehavior的实现.
>创建一个继承自Attribute的IServiceBehavior,并应用步骤2的行为.
步骤1 – IOperationInvoker
IOperationInvoker的关键是Invoke方法.我的类包装在一个try-catch块中的基本调用者:
public class LoggingOperationInvoker : IOperationInvoker { IOperationInvoker _baseInvoker; string _operationName; public LoggingOperationInvoker(IOperationInvoker baseInvoker,DispatchOperation operation) { _baseInvoker = baseInvoker; _operationName = operation.Name; } // (TODO stub implementations) public object Invoke(object instance,object[] inputs,out object[] outputs) { MyInfrastructure.LogStart(_operationName,inputs); try { return _baseInvoker.Invoke(instance,inputs,out outputs); } catch (Exception ex) { MyInfrastructure.LogError(_operationName,ex); return null; } MyInfrastructure.LogEnd("Add",parameters); } }
步骤2 – IOperationBehavior
IOperationBehavior的实现简单地将自定义分派器应用于操作.
public class LoggingOperationBehavior : IOperationBehavior { public void ApplyDispatchBehavior(OperationDescription operationDescription,DispatchOperation dispatchOperation) { dispatchOperation.Invoker = new LoggingOperationInvoker(dispatchOperation.Invoker,dispatchOperation); } // (TODO stub implementations) }
步骤3 – IServiceBehavior
IServiceBehavior的这种实现将操作行为应用于服务;它应该从属性继承,以便它可以作为属性应用于WCF服务类.这个实现是标准的.
public class ServiceLoggingBehavior : Attribute,IServiceBehavior { public void ApplyDispatchBehavior(ServiceDescription serviceDescription,ServiceHostBase serviceHostBase) { foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints) { foreach (OperationDescription operation in endpoint.Contract.Operations) { IOperationBehavior behavior = new LoggingOperationBehavior(); operation.Behaviors.Add(behavior); } } } }