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

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


一开始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 ;
} public Task TestAsync()
{
Console.WriteLine("TestAsync"); return Task.CompletedTask;
} public Task<int> TestIntAsync()
{
Console.WriteLine("TestIntAsync"); return Task.FromResult();
}
}

打上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 ;
} public Task TestAsync()
{
Console.WriteLine("TestAsync"); return Task.CompletedTask;
} public Task<int> TestIntAsync()
{
Console.WriteLine("TestIntAsync"); return Task.FromResult();
}
}

这样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的知识

NCoreCoder.Aop详解的更多相关文章

  1. Spring4 AOP详解

    Spring4 AOP详解 第一章Spring 快速入门并没有对Spring4 的 AOP 做太多的描述,是因为AOP切面编程概念不好理解.所以这章主要从三个方面详解AOP:AOP简介(了解),基于注 ...

  2. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  3. [Spring学习笔记 5 ] Spring AOP 详解1

    知识点回顾:一.IOC容器---DI依赖注入:setter注入(属性注入)/构造子注入/字段注入(注解 )/接口注入 out Spring IOC容器的使用: A.完全使用XML文件来配置容器所要管理 ...

  4. AOP 详解

    1. 需求:统计方法执行的性能情况(来源:<精通Spring 4.x>) // 性能监视类 PerformanceMonitor package com.noodles.proxy; pu ...

  5. Spring AOP详解(转载)所需要的包

    上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑 ...

  6. Spring AOP详解及简单应用

    Spring AOP详解   一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...

  7. 转:Spring AOP详解

    转:Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...

  8. Spring全家桶——SpringBoot之AOP详解

    Spring全家桶--SpringBoot之AOP详解 面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方 ...

  9. Spring Aop 详解二

    这是Spring Aop的第二篇,案例代码很详解,可以查看https://gitee.com/haimama/java-study/tree/master/spring-aop-demo. 阅读前,建 ...

随机推荐

  1. .NET Core使用AngleSharp网络数据采集

    环境: vs2019 .net core 3.1 angleSharp winform 安装:angleSharp 有这么一本Python的书: <<Python 网络数据采集>&g ...

  2. Redis实例讲解

    简介 Redis是一个key-value的nosql产品,和我们熟知的Memcached有些类似,但他存储value类型相对更加丰富,包括string(字符串),list(链表),set(集合),zs ...

  3. softmax、cross entropy和softmax loss学习笔记

    之前做手写数字识别时,接触到softmax网络,知道其是全连接层,但没有搞清楚它的实现方式,今天学习Alexnet网络,又接触到了softmax,果断仔细研究研究,有了softmax,损失函数自然不可 ...

  4. Newbe.Claptrap 框架中为什么用 Claptrap 和 Minion 两个词?

    Newbe.Claptrap 框架中为什么用 Claptrap 和 Minion 两个词?最近整理了一下项目的术语表.今天就谈谈为什么起了 Claptrap 和 Minion 两个名字. Claptr ...

  5. p46_IPv4地址

    IP地址:全世界唯一的32位/4字节标识符,标识路由器主机的接口. IP地址::={<网络号>,<主机号>} 图中有6个子网 比如222.1.3.0是网络号,3是主机号,222 ...

  6. java valid 注解使用-java validation注解详解

    注解 描述 @AssertFalse 带注解的元素必须为false,支持boolean/Boolean @AssertTrue 带注解的元素必须为true,支持boolean/Boolean @Dec ...

  7. Just test it!!软件测试测起来!!

    (图片: josh@unsplash,字数:700,时间:1分钟) (一) 一切的软件质量保障活动,归根结底,就两种类型. 一种是基于代码执行的,一种是不基于代码执行的. 测试之于肉眼自查.静态检查. ...

  8. 在 Docker 搭建 Maven 私有库

    在 Docker 搭建 Maven 私有库 小引 If you are developing software without a repository manager you are likely ...

  9. LeetCode 86 | 链表基础,一次遍历处理链表中所有符合条件的元素

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题第53篇文章,我们一起来看LeetCode第86题,Partition List(链表归并). 本题的官方难度是M ...

  10. 图像增强 | CLAHE 限制对比度自适应直方图均衡化

    1 基本概述 CLAHE是一个比较有意思的图像增强的方法,主要用在医学图像上面.之前的比赛中,用到了这个,但是对其算法原理不甚了解.在这里做一个复盘. CLAHE起到的作用简单来说就是增强图像的对比度 ...