【问题标题】:Logging using AOP in .NET Core 2.1在 .NET Core 2.1 中使用 AOP 进行日志记录
【发布时间】:2019-02-09 23:14:10
【问题描述】:

我想为我的 .NET Core 2.1 解决方案中的日志记录实现 AOP。我以前从未使用过它,我一直在网上寻找,似乎看不到任何使用 Core 2 的人的例子。有人知道我会怎么做吗?

例如,哪些包用于 AOP,有任何示例代码可以帮助我入门吗?我使用带有 .net 核心的内置 DI,所以我不需要担心那部分。

【问题讨论】:

标签: c# logging asp.net-core aop asp.net-core-2.1


【解决方案1】:

Microsoft DI 不提供拦截器或装饰器等高级方案(有一个使用 Microsoft DI 的装饰器的解决方法:https://medium.com/@willie.tetlow/net-core-dependency-injection-decorator-workaround-664cd3ec1246)。

您可以使用 Autofac (https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html) 或带有动态代理的简单注入器来实现 AOP。两者都有一个非常好的文档。由于其设计规则,简单注入器没有开箱即用的拦截解决方案,但您可以为其添加扩展 (http://simpleinjector.readthedocs.io/en/latest/aop.html)。

这是来自官方 SI 文档的基本 AOP 场景:(http://simpleinjector.readthedocs.io/en/latest/InterceptionExtensions.html):

//Add registration to the composition root
container.InterceptWith<MonitoringInterceptor>(serviceType => serviceType.Name.EndsWith("Repository"));`

// Here is an example of an interceptor implementation.
// NOTE: Interceptors must implement the IInterceptor interface:
private class MonitoringInterceptor : IInterceptor {
    private readonly ILogger logger;

  public MonitoringInterceptor(ILogger logger) {
        this.logger = logger;
    }

    public void Intercept(IInvocation invocation) {
        var watch = Stopwatch.StartNew();

        // Calls the decorated instance.
        invocation.Proceed();

        var decoratedType = invocation.InvocationTarget.GetType();

        this.logger.Log(string.Format("{0} executed in {1} ms.",
            decoratedType.Name, watch.ElapsedMilliseconds));
    }
}

【讨论】:

    【解决方案2】:

    免责声明:我是此解决方案的制作者

    Microsoft 确实为 Net Core 提供现成的 AOP 解决方案。但是,我制作了一个可能会有所帮助的第 3 方项目。它直接与 Net Core 一起工作,并通过您的应用程序中的 ServiceCollection 注册插入。

    Microsoft 提供的是一个名为 System.Runtime.DispatchProxy 的库,可用于为您的类创建代理对象。然而,这个代理本身并不是特别有用或功能丰富,并且需要大量额外的代码才能获得与 Castle Proxy(众所周知的动态代理库)相当的东西

    考虑到这一点,我创建了一个库,它将 DispatchProxy 包装到可以在应用程序启动的 ServiceCollection 配置期间轻松注入的代码中。诀窍是有一种方法来创建属性和可以应用于您的方法的配对拦截器。然后在代理包装期间读取该属性并调用相关的拦截器。

    这是一个示例拦截器属性

    public class ConsoleLogAttribute : MethodInterceptorAttribute
    {
    }
    

    这是一个示例拦截器类

    public class ConsoleLogInterceptor : MethodInterceptor
    {
        public override void BeforeInvoke(IInterceptionContext interceptionContext)
        {
            Console.WriteLine($"Method executing: {interceptionContext.CurrentMethod.Name}");
        }
    
        public override void AfterInvoke(IInterceptionContext interceptionContext, object methodResult)
        {
            Console.WriteLine($"Method executed: {interceptionContext.CurrentMethod.Name}");
        }
    }
    

    这就是它将如何应用于您的方法

    [ConsoleLog]
    public void TestMethod()
    {
    }
    

    最后,这就是将它添加到您的 ServiceCollection 配置中的方式(假设您想要代理的类称为 [TestClass]:

    public void ConfigureServices(IServiceCollection services)
    {
        // Configure Simple Proxy
        services.EnableSimpleProxy(p => p.AddInterceptor<ConsoleLogAttribute, ConsoleLogInterceptor>());
    
        // Configure your services using the Extension Methods
        services.AddTransientWithProxy<ITestClass, TestClass>();
    }
    

    看看这个 GitHub 项目:https://github.com/f135ta/SimpleProxy

    【讨论】:

    • 注意:该项目现已更新为使用 Castle DynamicProxy 代替
    • 图书馆看起来很有趣,谢谢分享。但是在 nuget 依赖项页面上说“.NETCoreApp 2.2”需要使用这个简单的代理 - 所以,强迫用户使用 .net core 2.2 是个坏主意。因为 .net core 2.1 是 LTS(长期支持)版本。 2.2 不是。并且还询问了“在 .net Core 2.1 中使用 aop 进行日志记录”的问题。
    • 我写的时候刚拿了最新的NetCore版本。您可以下载代码并将依赖框架更改为 2.1,如果它让您更舒服。
    • 你好图书馆看起来很不错。存在任何拦截异常的方法,例如:void OnException(InvocationContext ...) 谢谢。
    • 我喜欢这个...但是“SimpleProxy 是否正在积极开发?...”并没有引起极大的信心。
    猜你喜欢
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 2015-08-18
    相关资源
    最近更新 更多