17

我需要记录 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

我意识到这可以使用面向方面的编程来完成,但在 C# 中,唯一的方法是修改字节码,这需要使用像 PostSharp 这样的第三方产品。我想避免使用商业图书馆。

笔记2

请注意,Silverlight 应用程序是该服务的主要使用者。

注意#3

在某些情况下, WCF 跟踪日志记录是一个不错的选择,但它在这里不起作用,因为如上所述,我需要检查返回值,如果发生异常更改,则需要检查返回值。

4

2 回答 2

28

是的,可以使用WCF 中内置的扩展点来封装这种日志记录。实际上有多种可能的方法。我在这里描述的添加了一个IServiceBehavior,它使用了一个 custom IOperationInvoker,并且不需要任何 web.config 修改。

这包括三个部分。

  1. 创建 的实现IOperationInvoker,它将方法调用包装在所需的日志记录和错误处理中。
  2. 创建一个IOperationBehavior应用从步骤 1 开始的调用程序的实现。
  3. 创建一个IServiceBehavior,它继承自Attribute,并应用第 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, inputs, 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将操作行为应用于服务;它应该继承自,Attribute以便它可以作为 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);
            }
        }
    }
}
于 2012-12-01T01:44:09.343 回答
5

您可以尝试Audit.NET库及其Audit.WCF扩展。它可以记录 WCF 服务交互并兼容异步调用。

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

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

WCF 扩展使用IOperationInvoker实现InvokeInvokeBegin/ InvokeEnd。你可以在这里查看代码。

于 2018-01-15T06:36:34.627 回答