zoukankan      html  css  js  c++  java
  • NCoreCoder.Aop详解

    于今天,功能终于完善度到比较满意的程度了

    准备好好写一篇文章,而不是之前的流水账,分享一下最近这些天的踩坑


    一开始AOP选的微软提供的DispatchProxy

    关于这个,有大佬的文章,可以看看,了解一下

    https://www.cnblogs.com/ElderJames/p/implement-simple-Aop-using-a-dotnet-core-library-System-Reflection-DispatchProxy.html

    初步完成后,发现几个大问题,异步不支持,不支持构造器注入,代理类必须是继承DispatchProxy的公开类

    我就想到我偶像Lemon大佬的著作AspectCore了,依稀记得是Emit构建的代理类

    也有代码可以参考学习,那就开干,前后四天多的时间,终于完工

    下面介绍一下我的AOP组件 NCoreCoder.Aop的使用以及高级应用


    简单的使用NCoreCoder.Aop

    NCoreCoder.Aop支持依赖注入,用依赖注入的方式完成代理类和接口的关联

    支持.Net Core 3.0以及以下的依赖注入方式

    示例

        public interface IMyClass
        {
            void TestVoid();
            int TestInt();
            Task TestAsync();
            Task<int> TestIntAsync();
        }
    
        [JitInject]
        internal class MyClass : IMyClass
        {
            public void TestVoid()
            {
                Console.WriteLine("TestVoid");
            }
    
            public int TestInt()
            {
                Console.WriteLine("TestInt");
    
                return 100;
            }
    
            public Task TestAsync()
            {
                Console.WriteLine("TestAsync");
    
                return Task.CompletedTask;
            }
    
            public Task<int> TestIntAsync()
            {
                Console.WriteLine("TestIntAsync");
    
                return Task.FromResult(100);
            }
        }

    打上JitInject特性是证明这个类需要实现代理

    这里就只是构建代理类,没有方法并走代理流程,代理支持 同步API、异步无返回值API、异步有返回值API

    要拦截的方法,默认是继承JitAopAttribute,打特性方式完成拦截器注入

    打在继承的实现类上

    比如

        [AttributeUsage(AttributeTargets.Method)]
        internal class TestJitAttribute : JitAopAttribute
        {
            public override void Before(MethodReflector method, object instance, params object[] param)
            {
            }
    
            public override void After(MethodReflector method, object instance, params object[] param)
            {
            }
    
            public override Task BeforeAsync(MethodReflector method, object instance, params object[] param)
            {return Task.CompletedTask;
            }
    
            public override Task AfterAsync(MethodReflector method, object instance, params object[] param)
            {return Task.CompletedTask;
            }
        }

    在需要拦截的方法上,打上TestJit即可

            [TestJit]
            public void TestVoid()
            {
                Console.WriteLine("TestVoid");
            }
    
            public int TestInt()
            {
                Console.WriteLine("TestInt");
    
                return 100;
            }
    
            public Task TestAsync()
            {
                Console.WriteLine("TestAsync");
    
                return Task.CompletedTask;
            }
    
            public Task<int> TestIntAsync()
            {
                Console.WriteLine("TestIntAsync");
    
                return Task.FromResult(100);
            }
        }

    这样TestVoid方法就要走AOP流程了

    Asp.Net Core 3.0以下

    因为Asp.Net Core 3.0以下的Startup.ConfigService方法支持直接修改返回值变成IServiceProvider

    所以在Asp.Net Core 3.0以下,依赖注入都是在Startup.ConfigService里面修改IServiceProvider到自定义的IServiceProvider完成替换依赖注入容器和流程的效果,比如Autofac

            public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc();
                //略略略
            }

    改为

            public IServiceProvider ConfigureServices(IServiceCollection services)
            {
                services.AddMvc();
                //略略略
                service.AddSingleton<IMyClass, MyClass>();
    
                //修改Ioc容器流程
                return service.BuilderJit();
            }

    Asp.Net Core 3.0

    Asp.Net Core 3.0的替换依赖注入流程变了

    无法再修改Startup.ConfigService返回值了,只要不是void,运行就抛出异常

    查看的Program.CreateHostBuilder

            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });

    改为

            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .UseServiceProviderFactory(new JitServiceProviderFactory()) //新增
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });

    这里可以保持原有依赖注入,也可以增加一个方法

            public void ConfigureContainer(JitAopBuilder builder)
            {
                builder.Add<IMyClass, MyClass>(ServiceLifetime.Singleton);
            }

    测试Aop

                var service = new ServiceCollection();
    
                service.AddSingleton<IMyClass, MyClass>();
    
                var serviceProvider = service.BuilderJit();
    
                TypeBuilderFactory.Instance.Save();
    
                var myclass = serviceProvider.GetRequiredService<IMyClass>();
    
                Task.Factory.StartNew(async () =>
                {
                    myclass.TestVoid();
                    var result1 = myclass.TestInt();
    
                    await myclass.TestAsync();
                    var result2 = await myclass.TestIntAsync();
                });
    
                Console.ReadLine();

    我们运行看看myclass对象是什么~

    不是原有的MyClass对象


    高级扩展

    我们现在如果要针对不同流程,而不是默认的Before->After

    那么我们就需要自定义一个IAopActors了

    我们默认的JitAopAttribute的流程就是一个默认DefaultAopActors

    编写一个公开的类,继承自IAopActors

    IAopActors接口如下

    然后再接口上打上特性AopActorsAttribute

    特性的构造参数是Type对应了自定义的AopActors的Type

        public class TestActors : IAopActors
        {
            public object Execute(AopContext context)
            {
                throw new NotImplementedException();
            }
    
            public Task<TResult> ExecuteAsync<TResult>(AopContext context)
            {
                throw new NotImplementedException();
            }
    
            public Task InvokeAsync(AopContext context)
            {
                throw new NotImplementedException();
            }
        }
        [AopActors(typeof(TestActors))]
        public interface IMyClass
        {
            void TestVoid();
            int TestInt();
            Task TestAsync();
            Task<int> TestIntAsync();
        }

    个人文笔不好,如有疑问,可以加“.Net应用程序框架交流” 群号386092459 欢迎到群里和我反馈Bug或者建议、交流Aop设计和Emit的知识

  • 相关阅读:
    搭建企业级Docker Registry -- Harbor
    搭建私服-docker registry
    CentOS 7.2修改网卡名称
    tomcat错误日志监控脚本
    Openresty+Lua+Redis灰度发布
    Jenkins权限控制-Role Strategy Plugin插件使用
    Rsyslog日志服务搭建
    awk4.0对数组value排序
    Spring-IOC 在非 web 环境下优雅关闭容器
    Spring-IOC bean 生命周期之 Lifecycle 钩子
  • 原文地址:https://www.cnblogs.com/NCoreCoder/p/11597788.html
Copyright © 2011-2022 走看看