Yes, it is possible to encapsulate this kind of logging, using the extensibility points built into WCF. There are actually multiple possible approaches. The one I'm describing here adds an IServiceBehavior
, which uses a custom IOperationInvoker
, and does not require any web.config modifications.
There are three parts to this.
- Create an implementation of
IOperationInvoker
, which wraps the method invocation in the required logging and error-handling.
- Create an implementation of
IOperationBehavior
that applies the invoker from step 1.
- Create an
IServiceBehavior
, which inherits from Attribute
, and applies the behavior from step 2.
Step 1 - IOperationInvoker
The crux of IOperationInvoker is the Invoke
method. My class wraps the base invoker in a try-catch block:
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);
}
}
Step 2 - IOperationBehavior
The implementation of IOperationBehavior simply applies the custom dispatcher to the operation.
public class LoggingOperationBehavior : IOperationBehavior
{
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Invoker = new LoggingOperationInvoker(dispatchOperation.Invoker, dispatchOperation);
}
// (TODO stub implementations)
}
Step 3 - IServiceBehavior
This implementation of IServiceBehavior
applies the operation behavior to the service; it should inherit from Attribute
so that it can be applied as an attribute to the WCF service class. The implementation for this is standard.
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);
}
}
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…