Dora.Interception,为.NET Core度身打造的AOP框架 [4]:与依赖注入框架的无缝集成
Dora.Interception最初的定位就是专门针对.NET Core的AOP框架,所以在整个迭代过程中我大部分是在做减法。对于.NET Core程序开发来说,依赖注入已经成为无处不在并且“深入骨髓”的东西,不论是在进行业务应用的开发,还是进行基础组件的开发,依赖注入是实现“松耦合”最为理想的方式(没有之一)。对于绝大部分AOP框架来说,它们最终都会体现为创建一个能够拦截的“代理对象”来实现对方法调用的拦截,但是.NET Core中针对服务实例的提供完全由通过IServiceProvider接口表示的DI容器来接管,所以Dora.Interception必须将两者无缝地集成在一起。与依赖注入框架的集成不仅仅体现在对可被拦截的代理对象的创建,同样应用在了针对拦截器的定义和注册上。
一、IInterceptable<T>
由于.NET Core总是采用IServiceProvider接口表示的DI容器来提供注入的依赖服务对象,现在我们得将原始的目标对象转换成能够被拦截代理对象,为此我们提供了一个泛型的服务接口IInterceptable<T>,它的Proxy属性返回的就是这么一个代理对象。
public interface IInterceptable<T> where T: class { T Proxy { get; } }
由于着了一个帮助我们提供可拦截代理的IInterceptable<T>服务,我们就可以在需要拦截目标类型的地方按照如下的方式注入该服务,并利用其Proxy属性得到这个可被拦截的代理。
public class HomeController : Controller { private readonly ISystemClock _clock; public HomeController(IInterceptable<ISystemClock> clockAccessor) { _clock = clockAccessor.Proxy; Debug.Assert(typeof(SystemClock) != _clock.GetType()); } }
二、让IServiceProvider直接代理对象
在被依赖类型的构造函数中注入IInterceptable<T>服务的编程方式总显得有点别扭,这要求所有具有AOP需求的组件都需要依赖Dora.Interception,这无疑是不现实的。我们最终需要解决的还是如何让IServiceProvider直接提供可被拦截的代理对象,为此我对.NET Core依赖注入框架的源代码作了一点很小的改动。这个经过简单修改的IServiceProvider实现类型就是如下这个InterceptableServiceProvider 类型。至于具体修改了什么,并不是一两句话就能说清楚的,这涉及到整个依赖注入框架的设计,有兴趣有查看源代码。
internal sealed class InterceptableServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback { internal InterceptableServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options, IInterceptingProxyFactory interceptingProxyFactory); public void Dispose(); public object GetService(Type serviceType); void IServiceProviderEngineCallback.OnCreate(IServiceCallSite callSite); void IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope); }
我们在Startup类型的ConfigureServices方法中,调用IServiceCollection的扩展方法BuildInterceptableServiceProvider创建的就是这么一个InterceptableServiceProvider 对象。
public class Startup { public IServiceProvider ConfigureServices(IServiceCollection services) { return services ... .BuildInterceptableServiceProvider(); } ... }
三、服务注册
Dora.Interception所需的服务注册都是通过调用IServiceCollection的扩展方法AddInterception来完成的,由于AddInterception会调整现有的服务注册以支持上面介绍的IInterceptable<T>服务,所以AddInterception方法的调用需要放在所有服务注册结束之后。创建InterceptableServiceProvider的BuildInterceptableServiceProvider方法内部会调用AddInterception方法,但是不会对现有的服务注册作任何修改。
public static class ServiceCollectionExtensions { public static IServiceCollection AddInterception(this IServiceCollection services, Action<InterceptionBuilder> configure = null); public static IServiceProvider BuildInterceptableServiceProvider(this IServiceCollection services, Action<InterceptionBuilder> configure = null); public static IServiceProvider BuildInterceptableServiceProvider(this IServiceCollection services, bool validateScopes, Action<InterceptionBuilder> configure = null); }
AddInterception和BuildInterceptableServiceProvider方法均定义了一个Action<InterceptionBuilder>类型的参数,我们可以利用它对注册的服务做进一步定制。比如如果我们需要实现自定义的拦截器注册方式,只需要将自定义的IInterceptorProviderResolver对象添加到InterceptorProviderResolvers 属性表示的集合中即可。
public class InterceptionBuilder { public InterceptionBuilder(IServiceCollection services); public InterceptorProviderResolverCollection InterceptorProviderResolvers { get; } public IServiceCollection Services { get; } }
[1]:更加简练的编程体验
[2]:基于约定的拦截器定义方式
[3]:多样性的拦截器应用方式
[4]:与依赖注入框架的深度整合
[5]:对拦截机制的灵活定制
相关文章
- ASP.NET MVC 模式的优缺点「建议收藏」
- JetBrains Rider mac/win(跨平台.NET IDE集成开发)最新版
- R-CNN、SPP-Net、Fast R-CNN…你都掌握了吗?一文总结目标检测必备经典模型(一)
- 【愚公系列】2022年12月 .NET CORE工具案例-.NET Core使用ExcelMapper
- [转载].NET性能优化-使用RecyclableMemoryStream替代MemoryStream
- 【愚公系列】2023年02月 .NET CORE工具案例-ChatGPT和.NET Core应用的结合
- Rider 2022.3.3(跨平台.NET IDE集成开发)
- .net让Oracle与ASP.NET实现无缝连接(oracleasp)
- Net开发Oracle数据库新技术攻关挑战(.net开发oracle)
- NET与Oracle结合出现新的可能(.net oracle)
- CMySQL与NET技术融会贯通(c mysql .net)
- net与Mysql实现数据库集成(.net集成mysql)
- Net调用MySQL技术实践(.net 调用mysql)
- NET操作MySQL数据库快速入门(.net读写mysql)
- NET备份MySQL提升数据安全性(.net 备份mysql)
- 基于NET的MySQL数据库开发实践(.net中使用mysql)
- ASP.NET数据库编程之处理文件访问许可
- jquery异步调用页面后台方法‏(asp.net)
- asp.net(c#)下读取word文档的方法小结
- sqlserver中批量插入与更新两种解决方案分享(asp.net)
- Asp.net内置对象之Server对象(概述及应用)
- .Net中导出数据到Excel(asp.net和winform程序中)
- Asp.net的GridView控件实现单元格可编辑方便用户使用
- ASP.NET服务器端控件RadioButtonList,DropDownList,CheckBoxList的取值、赋值用法
- .net生成缩略图及水印图片时出现GDI+中发生一般性错误解决方法