【问题标题】:Logging as a cross-cutting concern in WCF日志记录作为 WCF 中的横切关注点
【发布时间】:2016-01-01 20:38:41
【问题描述】:

我想在每次调用我的 Web 服务时记录到文件,记录被调用方法的名称以及调用数据。

要写入此文件,我使用Nlog,但我不想在我的每个服务操作中进行日志记录调用。我宁愿以某种方式自动执行此日志记录调用作为横切关注点。

有可能吗?

【问题讨论】:

    标签: c# wcf logfile


    【解决方案1】:

    您可以使用支持拦截器的 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(...);
    

    直接创建只是一个例子,当然你可以使用构造函数或属性注入来代替,如果需要的话,可以用工厂替换客户端接口。

    希望对你有帮助!

    【讨论】:

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

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

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 2015-09-27
          • 1970-01-01
          • 2021-10-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多