Atributo de servicio WCF para registrar llamadas de método y excepciones

Tengo un requisito para registrar cada llamada al método en un servicio WCF y cualquier excepción lanzada. Esto ha llevado a una gran cantidad de código redundante, ya que cada método debe incluir un texto similar al siguiente:

[OperationContract] public ResultBase 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("Oops, the request failed", ex); } MyInfrastructure.LogEnd("Add", parameters); } 

¿Hay alguna manera de que pueda encapsular toda esta lógica en un atributo MyServiceLoggingBehaviorAttribute , que podría aplicar a la clase de servicio (o métodos) como esta:

 [ServiceContract] [MyServiceLoggingBehavior] public class MyService { } 

Nota 1

Me doy cuenta de que esto se puede hacer utilizando la progtwigción orientada a Aspect , pero en C # la única forma de hacerlo es modificar bytecode, que requiere el uso de un producto de terceros como PostSharp. Me gustaría evitar el uso de bibliotecas comerciales.

Nota 2

Tenga en cuenta que las aplicaciones de Silverlight son los principales consumidores del servicio.

Nota 3

El registro de seguimiento de WCF es una buena opción en algunos casos, pero no funciona aquí porque, como se indicó anteriormente, debo inspeccionar, y en el caso de un cambio de excepción, el valor de retorno.

Sí, es posible encapsular este tipo de registro utilizando los puntos de extensibilidad incorporados en WCF . En realidad, hay múltiples enfoques posibles. El que estoy describiendo aquí agrega un IServiceBehavior , que usa un IOperationInvoker personalizado, y no requiere ninguna modificación de web.config.

Hay tres partes para esto.

  1. Cree una implementación de IOperationInvoker , que envuelve la invocación del método en el registro requerido y el manejo de errores.
  2. Cree una implementación de IOperationBehavior que aplique el invocador desde el paso 1.
  3. Cree un IServiceBehavior , que hereda de Attribute , y aplica el comportamiento desde el paso 2.

Paso 1 – IOperationInvoker

El quid de IOperationInvoker es el método Invoke . Mi clase envuelve al invocador de base en un bloque 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, inputs, ex); return null; } MyInfrastructure.LogEnd("Add", parameters); } } 

Paso 2 – Comportamiento de IOperation

La implementación de IOperationBehavior simplemente aplica el despachador personalizado a la operación.

 public class LoggingOperationBehavior : IOperationBehavior { public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.Invoker = new LoggingOperationInvoker(dispatchOperation.Invoker, dispatchOperation); } // (TODO stub implementations) } 

Paso 3 – Comportamiento de IService

Esta implementación de IServiceBehavior aplica el comportamiento de operación al servicio; debe heredar de Attribute para que pueda aplicarse como un atributo a la clase de servicio WCF. La implementación para esto es estándar.

 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); } } } } 

Puede probar la biblioteca Audit.NET con su extensión Audit.WCF . Puede registrar la interacción del servicio WCF y es compatible con las llamadas asincrónicas.

Todo lo que necesita hacer es decorar su clase de servicio WCF o métodos con el atributo AuditBehavior :

 [AuditBehavior()] public class OrderService : IOrderService { ... } 

La extensión WCF usa un IOperationInvoker implementa Invoke e InvokeBegin / InvokeEnd . Puedes consultar el código aquí .