WCF服务属性用于记录方法调用和异常

时间:2012-12-01 01:44:09

标签: c# wcf logging custom-attributes aop

我需要在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在某些情况下是一个不错的选择,但它在这里不起作用,因为如上所述,我需要检查,并且在异常更改的情况下,返回值。

2 个答案:

答案 0 :(得分:26)

是的,可以使用extensibility points built into WCF封装此类日志记录。实际上有多种可能的方法。我在这里描述的那个添加IServiceBehavior,它使用自定义IOperationInvoker,并且不需要任何web.config修改。

这有三个部分。

  1. 创建IOperationInvoker的实现,它将方法调用包装在所需的日志记录和错误处理中。
  2. 创建IOperationBehavior的实现,该实现应用步骤1中的调用者。
  3. 创建一个继承自IServiceBehavior的{​​{1}},并应用第2步中的行为。
  4. 第1步 - IOperationInvoker

    IOperationInvoker的关键是Attribute方法。我的类将基本调用程序包装在try-catch块中:

    Invoke

    第2步 - IOperationBehavior

    IOperationBehavior的实现只是将自定义调度程序应用于操作。

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

    第3步 - IServiceBehavior

    public class LoggingOperationBehavior : IOperationBehavior { public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.Invoker = new LoggingOperationInvoker(dispatchOperation.Invoker, dispatchOperation); } // (TODO stub implementations) } 的此实现将操作行为应用于服务;它应该从IServiceBehavior继承,以便它可以作为属性应用于WCF服务类。这方面的实施是标准的。

    Attribute

答案 1 :(得分:3)

您可以使用Audit.NET扩展程序试用Audit.WCF库。它可以记录WCF服务交互并与异步调用兼容。

您需要做的就是使用AuditBehavior属性修饰您的WCF服务类或方法:

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

WCF扩展程序使用IOperationInvoker实施InvokeInvokeBegin / InvokeEnd。您可以查看代码here