ABP依赖注入
ASP.NET CORE自带的Microsoft.Extensions.DependencyInjection 依赖注入容器 不支持属性注入 不支持批量注入
ABP使用依赖注入框架是Castle.Windsor
.NET Core创建的项目返回类型是ConfigureService 在这里变成了IServiceProvider 这是因为在AddAbp方法内部替换了内置的Ioc容器
public IServiceProvider ConfigureServices(IServiceCollection services) { return services.AddAbp<HKAbpDemoHostModule>(); }
都是在module的Initialize(初始化)方法中注册程序集 实现了下面三种接口的都会被自动注册到依赖
public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); }
提供了三个自动实现依赖注入的接口
ITransientDependency 每次都是一个新实例
ISingletonDependency 全局共用一个实例
IPerWebRequestDependency 没用到过
实现这三个接口的自动依赖注入 在Abp.Dependency BasicConventionalRegistrar这个类中实现
public class BasicConventionalRegistrar : IConventionalDependencyRegistrar { public void RegisterAssembly(IConventionalRegistrationContext context) { //其注册所有继承至ITransientDependency,ISingletonDependency和IInterceptor接口的类。 //Transient context.IocManager.IocContainer.Register( //准备注册的类型 从获取传递过来的程序集 Classes.FromAssembly(context.Assembly) //扫描获取类 包括非公用的 .IncludeNonPublicTypes() //当前类型需要继承ITransientDependency .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() ); } }
每一个Module的初始化方法都会调用下面 IocManager.RegisterAssemblyByConvention() 这个方法会对当前程序集进行解析 实现上面三个接口的实现注入
public override void Initialize() { IocManager.RegisterAssemblyByConvention(typeof(IMSEntityFrameworkModule).GetAssembly()); }
比如要调用其他Applicaton中的方法
可以直接获取当前类型的实例然后调用里面的方法
await iocManager.Resolve<CustomerAddressAppService>().GetListByCustomerId(null);
- IIocRegistrar:用于注册依赖项的类的接口
- IIocResolver:用于解析依赖的类的接口
- IIocManager:用于注册和解析依赖项的接口
IIocManager
本身则是封装了一个 Castle Windsor 的 Ioc 容器
IocManager内部维护一个private readonly List<IConventionalDependencyRegistrar> _conventionalRegistrars; 存放了所有进行过注册的信息
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 name="type">Type to check</param> new bool IsRegistered(Type type); /// <summary> /// Checks whether given type is registered before. /// </summary> /// <typeparam name="T">Type to check</typeparam> new bool IsRegistered<T>(); }
public class MySampleClass : ITransientDependency { private readonly IIocResolver _iocResolver; public MySampleClass(IIocResolver iocResolver) { _iocResolver = iocResolver; } public void DoIt() { //解析, 使用并手动释放 var personService1 = _iocResolver.Resolve<PersonAppService>(); personService1.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" });
//调用Release来手动解析一个对象是很关键的,否则,应用会有内存泄漏问题。为了确保释放对象,要尽可能使用ResolveAsDisPosable(如例子中演示的那样)。在using块的末尾会自动地调用Release。 _iocResolver.Release(personService1); //解析并使用using语法糖来释放资源 using (var personService2 = _iocResolver.ResolveAsDisposable<PersonAppService>()) { personService2.Object.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" }); } } }
对于没有自动注册到DI容器的对象 可以通过下面的方式进行手动注册
在Startup.cs中 services.AddTransient<IHttpHelp, HttpHelp>();
IocManager.Register<IHttpHelp, HttpHelp>(DependencyLifeStyle.Transient);
构造函数注入执行顺序优先于属性注入
使用.NET Core 自带的依赖注入容器 后注册的会替换之前注册的
services.AddTransient<IPer, PersonA>(); var a = services.BuildServiceProvider().GetService<IPer>(); services.AddTransient<IPer, PersonB>(); var b = services.BuildServiceProvider().GetService<IPer>();
使用abp自带的Castle.Windsor依赖注入容器后 后注册的不会替换之前注册的
IocManager.Register<IPer, PersonA>();
IocManager.Register<IPer, PersonB>();
下面调用替换服务的方式也不会替换之前注册的服务,但是替换服务写在PreInitialize的生命周期函数中,会在Initialize声明周期开始的时候第一时间注入,抢先于按规约注入的方式
需要引用using Abp.Configuration.Startup;
Configuration.ReplaceService<IPer, PersonB>();