Dora.Interception[1]全新升级后,编程体验的是:编程体验能有多爽?

摘要:多年之前利用IL Emit写了一个名为Dora.Interception(github地址,觉得不错不妨给一颗星)的AOP框架。前几天利用Roslyn的Source Generator对自己为公司写的一个GraphQL框架进行改造,性能得到
多年之前利用IL Emit写了一个名为Dora.Interception(github地址,觉得不错不妨给一颗星)的AOP框架。前几天利用Roslyn的Source Generator对自己为公司写的一个GraphQL框架进行改造,性能得到显著的提高,觉得类似的机制同样可以用在AOP框架上,实验证明这样的实现方式不仅仅极大地改善性能(包括执行耗时和GC内存分配),而且让很多的功能特性变得简单了很多。这并不是说IL Emit性能不好(其实恰好相反),而是因为这样的实现太复杂,面向IL编程比写汇编差不多。由于AOP拦截机制涉及的场景很多(比如异步等待、泛型类型和泛型方法、按地址传递参数等等),希望完全利用IL Emit高效地实现所有的功能特性确实很难,但是从C#代码的层面去考虑就简单多了。((拙著《ASP.NET Core 6框架揭秘》6折优惠,首印送签名专属书签) 目录 一、Dora.Interception的设计特点 二、基于约定的拦截器定义 三、基于特性的拦截器注册方式 四、基于表达式的拦截器注册方式 五、更好的拦截器定义方式 六、方法注入 七、拦截的屏蔽 八、在ASP.NET Core程序中的应用 一、Dora.Interception的设计特点彻底改造升级后的Dora.Interception直接根据.NET 6开发,不再支持之前.NET (Core)版本。和之前一样,Dora.Interception的定位是一款轻量级的AOP框架,同样建立在.NET的依赖注入框架上,可拦截的对象必需由依赖注入容器来提供。 除了性能的提升和保持低侵入性,Dora.Interception在编程方式上于其他所有的AOP框架都不太相同。在拦截器的定义上,我们并没有提供接口和基类来约束拦截方法的实现,而是采用“基于约定”的编程模式将拦截器定义成一个普通的类,拦截方法上可以任意注入依赖的对象。 在如何应用定义的拦截器方面,我们提供了常见的“特性标注”的编程方式将拦截器与目标类型、方法和属性建立关联,我们还提供了一种基于“表达式”的拦截器应用方式。Dora.Interception主张将拦截器“精准”地应用到具体的目标方法上,所以提供的这两种方式针对拦截器的应用都是很“明确的”。如果希望更加灵活的拦截器应用方式,通过提供的扩展可以自由发挥。 接下来我们通过一个简单实例来演示一下Dora.Interception如何使用。在这个实例中,我们利用AOP的方式来缓存某个方法的结果,我们希望达到的效果很简单:目标方法将返回值根据参数列表进行缓存,以避免针对方法的重复执行。 二、基于约定的拦截器定义我们创建一个普通的控制台程序,并添加如下两个NuGet包的引用。前者正是提供Dora.Interception框架的NuGet包,后者提供的基于内存缓存帮助我们缓存方法返回值。 Dora.InterceptionMicrosoft.Extensions.Caching.Memory由于方法的返回值必须针对输入参数进行缓存,所以我们定义了如下这个类型Key作为缓存的键。作为缓存键的Key对象是对作为目标方法的MethodInfo对象和作为参数列表的对象数组的封装。
阅读全文