https://mp.weixin.qq.com/s/6zoLkEdKMZAs24OJq-nUSg
01
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());
}
}02
InterceptableServiceProvider
在被依赖类型的构造函数中注入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();
}
...
}03
服务注册
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; }
}
















