[Abp 源码分析]三、依赖注入

在 Abp 框架里面,无时无刻不存在依赖注入,关于依赖注入的作用与好处我就不在这里多加赘述了,网上有很多解释的教程。在 [Abp 源码分析]一、Abp 框架启动流程分析 里面已经说过,Abp 本身在框架初始化的时候我们就可以看到它使用 Castle Windsor 将 Asp.Net Core 自带的 IServiceProvider 替换掉了。

1.大体结构

在 Abp 框架当中,它的依赖注入相关的类型基本上都放在 Abp 项目的 Dependency 文件夹里面,下图是他们之间的依赖关系:

假装有图

2 代码解析 2.1 基本实现

IIocManager 是直接继承 IIocRegistrar 与 IIocResolver 的一个接口,通过名称我们就可以看出来他们的作用,IIocRegistrar 内部提供了组件注册的方法定义,而 IIocResolver 内部则是提供了解析已经注入的组件方法。在 IIocManager 本身则是封装了一个 Castle Windsor 的 Ioc 容器,定义如下:

/// <summary> /// This interface is used to directly perform dependency injection tasks. /// </summary> public interface IIocManager : IIocRegistrar, IIocResolver, IDisposable { /// <summary> /// Reference to the Castle Windsor Container. /// </summary> IWindsorContainer IocContainer { get; } /// <summary> /// Checks whether given type is registered before. /// </summary> /// <param>Type to check</param> new bool IsRegistered(Type type); /// <summary> /// Checks whether given type is registered before. /// </summary> /// <typeparam>Type to check</typeparam> new bool IsRegistered<T>(); }

那么我们来看看 IIocManager 的具体实现。

方法虽然看起来挺多,不过更多的只是在 Castle Windsor 上面进行了一层封装而已,可以看到 Register() 这个注册方法在其内部也是直接调用的 IWindsorContainer.Register() 来进行注入。

public void Register(Type type, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) { IocContainer.Register(ApplyLifestyle(Component.For(type), lifeStyle)); } 2.2 规约注入

我们重点说一说它的规约注入,什么是规约注入?

在上面的类图当中,可以看到有一个 IConventionalDependencyRegistrar 接口,并且该接口还拥有四个实现,我们以 BasicConventionalRegistrar 类为例子看看里面做了什么操作。

/// <summary> /// This class is used to register basic dependency implementations such as <see cref="ITransientDependency"/> and <see cref="ISingletonDependency"/>. /// </summary> public class BasicConventionalRegistrar : IConventionalDependencyRegistrar { public void RegisterAssembly(IConventionalRegistrationContext context) { //Transient context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .IncludeNonPublicTypes() .BasedOn<ITransientDependency>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .WithService.Self() .WithService.DefaultInterfaces() .LifestyleTransient() ); //Singleton context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .IncludeNonPublicTypes() .BasedOn<ISingletonDependency>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .WithService.Self() .WithService.DefaultInterfaces() .LifestyleSingleton() ); //Windsor Interceptors context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .IncludeNonPublicTypes() .BasedOn<IInterceptor>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .WithService.Self() .LifestyleTransient() ); } }

在 BasicConventionalRegistrar 内部,他会扫描传入的程序集,并且根据类型所继承的接口来进行自动注入,所以 Abp 定义了两个辅助注入接口,叫做ITransientDependency 和 ISingletonDependency,并且在下面还注入了拦截器。

这样的话,我们自己就不需要频繁的使用 IIocManager.Register() 方法来手动注入,只需要在自己的实现类或者接口上面,继承上述两个接口之一即可。

在 IocManager 内部维护了一个集合 _conventionalRegistrars。

/// <summary> /// List of all registered conventional registrars. /// </summary> private readonly List<IConventionalDependencyRegistrar> _conventionalRegistrars;

这个集合就是已经存在的规约注册器,在 AbpKernelModule 的预加载方法里面就使用 AddConventionalRegistrar() 方法来添加了 BasicConventionalRegistrar 注册器。代码在 AbpKernelModule.cs 的 45 行:

public override void PreInitialize() { IocManager.AddConventionalRegistrar(new BasicConventionalRegistrar()); // 其他代码 }

之后每当程序调用 IIocManager.RegisterAssemblyByConvention(Assembly assembly) 方法的时候,就会根据传入的 Assembly 来循环调用存放在集合里面注册器的 RegisterAssembly() 方法,当然你也可以随时定义一个 Registrar ,注册约定你也可以自己来编写。

public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config) { var context = new ConventionalRegistrationContext(assembly, this, config); foreach (var registerer in _conventionalRegistrars) { registerer.RegisterAssembly(context); } if (config.InstallInstallers) { IocContainer.Install(FromAssembly.Instance(assembly)); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfxgg.html