Dora.Interception最初的定位就是专门针对.NET Core的AOP框架,所以在整个迭代过程中我大部分是在做减法。对于.NET Core程序开发来说,依赖注入已经成为无处不在并且“深入骨髓”的东西,不论是在进行业务应用的开发,还是进行基础组件的开发,依赖注入是实现“松耦合”最为理想的方式(没有之一)。对于绝大部分AOP框架来说,它们最终都会体现为创建一个能够拦截的“代理对象”来实现对方法调用的拦截,但是.NET Core中针对服务实例的提供完全由通过IServiceProvider接口表示的DI容器来接管,所以Dora.Interception必须将两者无缝地集成在一起。与依赖注入框架的集成不仅仅体现在对可被拦截的代理对象的创建,同样应用在了针对拦截器的定义和注册上。
一、IInterceptable
由于.NET Core总是采用IServiceProvider接口表示的DI容器来提供注入的依赖服务对象,现在我们得将原始的目标对象转换成能够被拦截代理对象,为此我们提供了一个泛型的服务接口IInterceptable
public interface IInterceptablewhere T: class { T Proxy { get; } }
由于着了一个帮助我们提供可拦截代理的IInterceptable
public class HomeController : Controller { private readonly ISystemClock _clock; public HomeController(IInterceptableclockAccessor) { _clock = clockAccessor.Proxy; Debug.Assert(typeof(SystemClock) != _clock.GetType()); } }
二、让IServiceProvider直接代理对象
在被依赖类型的构造函数中注入IInterceptable
internal sealed class InterceptableServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback { internal InterceptableServiceProvider(IEnumerableserviceDescriptors, 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
public static class ServiceCollectionExtensions { public static IServiceCollection AddInterception(this IServiceCollection services, Actionconfigure = null); public static IServiceProvider BuildInterceptableServiceProvider(this IServiceCollection services, Action configure = null); public static IServiceProvider BuildInterceptableServiceProvider(this IServiceCollection services, bool validateScopes, Action configure = null); }
AddInterception和BuildInterceptableServiceProvider方法均定义了一个Action
public class InterceptionBuilder { public InterceptionBuilder(IServiceCollection services); public InterceptorProviderResolverCollection InterceptorProviderResolvers { get; } public IServiceCollection Services { get; } }
[1]:更加简练的编程体验
[2]:基于约定的拦截器定义方式
[3]:多样性的拦截器应用方式
[4]:与依赖注入框架的深度整合
[5]:对拦截机制的灵活定制