简体   繁体   English

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

[英]WCF service attribute to log method calls and exceptions

I have a requirement to log each method call in a WCF service, and any exceptions thrown. 我需要在WCF服务中记录每个方法调用,并抛出任何异常。 This has led to a lot of redundant code, because each method needs to include boilerplate similar to this: 这导致了许多冗余代码,因为每个方法都需要包含类似于此的样板:

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

Is there a way I can encapsulate all this logic into an attribute MyServiceLoggingBehaviorAttribute , which I could apply to the service class (or methods) like this: 有没有办法可以将所有这些逻辑封装到MyServiceLoggingBehaviorAttribute属性中,我可以将其应用于服务类(或方法),如下所示:

[ServiceContract]
[MyServiceLoggingBehavior]
public class MyService
{
}

Note #1 注意#1

I realize that this can be done using Aspect-oriented programming , but in C# the only way to do this is to modify bytecode, which requires the use of a third-party product like PostSharp. 我意识到这可以使用面向方面的编程来完成,但在C#中,唯一的方法是修改字节码,这需要使用像PostSharp这样的第三方产品。 I would like to avoid using commercial libraries. 我想避免使用商业图书馆。

Note #2 笔记2

Note that Silverlight applications are the primary consumers of the service. 请注意,Silverlight应用程序是该服务的主要使用者。

Note #3 注意#3

WCF trace logging is a good option in some cases, but it doesn't work here because, as noted above, I need to inspect, and in the case of an exception change, the return value. 在某些情况下, WCF跟踪日志记录是一个不错的选择,但它在这里不起作用,因为如上所述,我需要检查,并且在异常更改的情况下,返回值。

Yes, it is possible to encapsulate this kind of logging, using the extensibility points built into WCF . 是的,可以使用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. 我在这里描述的那个添加了一个IServiceBehavior ,它使用自定义IOperationInvoker ,并且不需要任何web.config修改。

There are three parts to this. 这有三个部分。

  1. Create an implementation of IOperationInvoker , which wraps the method invocation in the required logging and error-handling. 创建IOperationInvoker的实现,它将方法调用包装在所需的日志记录和错误处理中。
  2. Create an implementation of IOperationBehavior that applies the invoker from step 1. 创建IOperationBehavior的实现,该实现应用步骤1中的调用者。
  3. Create an IServiceBehavior , which inherits from Attribute , and applies the behavior from step 2. 创建一个继承自AttributeIServiceBehavior ,并应用步骤2中的行为。

Step 1 - IOperationInvoker 第1步 - IOperationInvoker

The crux of IOperationInvoker is the Invoke method. IOperationInvoker的关键是Invoke方法。 My class wraps the base invoker in a try-catch block: 我的类将基本调用程序包装在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);
    }
}

Step 2 - IOperationBehavior 第2步 - IOperationBehavior

The implementation of IOperationBehavior simply applies the custom dispatcher to the operation. IOperationBehavior的实现只是将自定义调度程序应用于操作。

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

    // (TODO stub implementations)
}

Step 3 - IServiceBehavior 第3步 - IServiceBehavior

This implementation of IServiceBehavior applies the operation behavior to the service; IServiceBehavior这种实现将操作行为应用于服务; it should inherit from Attribute so that it can be applied as an attribute to the WCF service class. 它应该从Attribute继承,以便它可以作为属性应用于WCF服务类。 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);
            }
        }
    }
}

You can try Audit.NET library with its Audit.WCF extension. 您可以尝试使用Audit.WCF扩展的Audit.NET库。 It can log the WCF service interaction and is compatible with async calls. 它可以记录WCF服务交互并与异步调用兼容。

All you need to do is decorate your WCF service class or methods with the AuditBehavior attribute: 您需要做的就是使用AuditBehavior属性装饰您的WCF服务类或方法:

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

The WCF extension uses an IOperationInvoker implementing Invoke and InvokeBegin / InvokeEnd . WCF扩展使用实现InvokeInvokeBegin / InvokeEndIOperationInvoker You can check the code here . 你可以在这里查看代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM