记录为WCF中的一个跨领域问题

时间:2016-01-01 20:38:42

标签: c# wcf logfile

每次调用我的Web服务时,我都想记录所调用方法的名称以及调用数据。

要写入此文件,我使用Nlog但我不希望在每个服务操作中进行日志记录调用。我更愿意以某种方式自动化这个日志记录调用作为交叉问题。

有可能吗?

3 个答案:

答案 0 :(得分:2)

您可以使用支持拦截器的DI容器来记录任何带有输入值的WCF方法调用。以下是Ninject和旧的奇怪ASMX服务的示例(对于WCF,想法是相同的):

让我们考虑以下客户端类:

public partial class LegacyClient : System.ServiceModel.ClientBase<Legacy>, Legacy

因为这个类是部分的,所以我们可以轻松地将包含我们想要调用的方法的接口ILegacyClient添加到类中。 ReSharper在一秒钟内提取界面。所以将部分类声明放在单独的文件中:

public partial class LegacyClient : ILegacyClient {}

在DI配置中,添加拦截器:

Kernel.Bind(typeof(ILegacyClient))
    .To<LegacyClient>()
    .InRequestScope() //carefully choose a scope
    .Intercept()
    .With<LogRequestInterceptor>();

LogRequestInterceptor是最有趣的部分:

using Ninject;
using Ninject.Extensions.Interception;

public class LogRequestInterceptor : IInterceptor 
{
    public void Intercept(IInvocation invocation)
    {
        MethodInfo method = invocation.Request.Method;

        var parameters = method.GetParameters();

        var builder = new StringBuilder();

        for (int index = 0; index < parameters.Length; index++)
        {
            object argument = invocation.Request.Arguments[index];

            ParameterInfo parameterInfo = parameters[index];

            if (!parameterInfo.IsOut)
            {
                //use any serialization you like
                string text = $"{parameterInfo.Name} = {argument.ToJson()}, ";

                builder.Append(text);
            }
        }

        string joinedParameters = builder.ToString();

        YourLogging(method.Name, joinedParameters); 

        //LegacyClient method call, don't forget this line
        invocation.Proceed();
    }
}

使事情有效的最后一部分。通过DI创建代理对象并使用它:

ILegacyClient client = Kernel.GetService<ILegacyClient>();
client.AnyMethodCall(...);

直接创建只是一个示例,当然您可以使用构造函数或属性注入,并在需要时将客户端接口替换为工厂。

希望它有所帮助!

答案 1 :(得分:1)

  1. 您可以尝试使用Windsor Castle,PostSharp或其他提供AOP的第三方库来进行面向方面编程(AOP)。此外,您可以使用这些库中的拦截器。

  2. WCF Extension可能是另一个进行此类记录的地方。

  3. 使用WCF跟踪。您可以通过配置启用WCF跟踪来查看服务调用,消息级别详细信息等。

答案 2 :(得分:0)

来自 Agalo 的回答是正确的但是过于笼统,所以我只想添加一个如何实现#2的链接。我想这正是作者想要的问题。

简而言之,您可以实现自己的参数检查器(IParameterInspector)并使用服务行为(IServiceBehavior)注入它。 Here you can find complete example how to do that用于记录。