老版Abp对Castle的严重依赖在vnext中已经得到了解决,vnext中DI容器可以任意更换,为了实现这个功能,底层架构相较于老版abp,可以说是进行了高度重构.当然这得益于.Net Core的DI容器组件本身的优势.接着abp vnext2.0核心组件之模块加载组件源码解析上文,上文中我跳过了DI切换这个流程,因为我觉得这是整个框架的亮点之一,所以单独写了这篇随笔.
.Net Core2.2之后,切换DI的实现换了,改成实现如下接口
1、核心ServiceProviderFactory接口实现
核心原理非常的简单,看看vnext如何实现这个工厂约束接口,并返回指定provider.
大致的逻辑是传入ServiceCollection,遍历ServiceCollection使用autofac的containerbuilder进行注入.最后调用containerbuilder实例的builder的build方法,返回provider.一气呵成,很简单.
接着,重点来了,看看Populate方法,看看其如何将ServiceCollection中的类型注入autofac容器的.
先将原生DI的相关功能转换成Autofac的,接着进行类型注册.
第一步获取模块加载类型中所有的模块,模块信息如下:
第二步释出DI容器中的ServiceRegistrationActionList,这个list非常重要.在DI默认容器转中的类型注入Autofac容器时,会遍历所有类型,并将类型的类型和实现生成上下文,传递给指定的action,实现代码如下:
看看vnext的示例代码如下:
简单的工作单元.
介绍了ServiceRegistrationActionList之后,接着看如下代码:
遍历所有的services集合,根据注入的方式和注入类型的差异进行区分,并注入到Autofac的ContainerBuilder中.代码很简单,挑个重点说下,如下:
红框中的第一行,代码如下:
如果当前类型所在的程序集属于应用程序集,不是与第三方程序集,则启动属性注入(反射的方式).
红框中的第二行就是上面介绍的遍历所有类型,生成上下文,并执行DI中注入的ServiceRegistrationActionList中的action,这里注意拦截器的注入,如下:
在执行完所有的Action之后,其中有部分Action,如下:
是向上下文中的拦截器集合追加拦截器的,所以当所有的action执行完毕之后,所有的拦截器也被写入到了拦截器集合中.下一步初始化拦截器。如下:
这边后续会写一篇随笔,专门介绍vnext中的拦截器的机制.涉及到另一个组件.本文就不介绍了.不是本文的重点.
顺便提一句
有能力的可以做一下这个todo.
ok,到这里所有的默认DI中的类型集合全部注入到了autofac中,并且完成了拦截器的初始化和应用程序框架的自动属性注入功能.
整个Populate方法执行完毕.AbpAutofacServiceProviderFactory的CreateBuilder方法也就结束了.最终将默认DI中的类型集合(IServiceCollection)转换成Autofac中的ContainerBuilder
接着看看CreateServiceProvider方法如下:
看看AutofacServiceProvider的构造,如下:
具体参考源码,实现了默认DI的获取Services接口。所以你可以继续用默认DI提供的方法,但是此时DI已被切换成了Autofac.
2、模块加载系统如何与之配合
接下去看看vnext的模块加载系统如何配合AbpAutofacServiceProviderFactory完成DI切换
第一步需要注入Autofac服务.
在注入核心的工厂服务后,且整个vnext框架的类型全部注入到默认DI中,那么需要触发核心工厂服务的相关方法如下:
继续观察ServiceCollectionCommonExtensions类下面的BuildServiceProviderFromFactory,如下
直接调用核心的工厂服务的CreateBuilder方法,这样所有默认DI中的类型全部注入到了autofac的容器中.并且切换默认DI容器到了autofac.替换默认DI的核心接口实现如下:
最后需要将模块加载系统中预先注入的ServiceProvider替换成核心的工厂服务的CreateBuilder方法执行后生成的ServiceProvider.
ok,整个DI切换流程到这里结束.abp团队的实现很简洁.如果你需要扩展其他的DI容器,可以参照他们的实现.
纯属个人理解,能力有限,有问题请指正!