【原创】ABP之IConventionalDependencyRegistra接口分析
类图:
作用:
abp中默认把对象的注册分为5中约定注册方式:
1.AbpAspNetCoreConventionalRegistrar
public class AbpAspNetCoreConventionalRegistrar : IConventionalDependencyRegistrar { public void RegisterAssembly(IConventionalRegistrationContext context) { //ViewComponents context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .BasedOn<ViewComponent>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .LifestyleTransient() ); //PerWebRequest context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .IncludeNonPublicTypes() .BasedOn<IPerWebRequestDependency>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .WithService.Self() .WithService.DefaultInterfaces() .LifestyleCustom<MsScopedLifestyleManager>() ); } }
2、ApiControllerConventionalRegistrar
/// <summary> /// Registers all Web API Controllers derived from <see cref="ApiController"/>. /// </summary> public class ApiControllerConventionalRegistrar : IConventionalDependencyRegistrar { public void RegisterAssembly(IConventionalRegistrationContext context) { context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .BasedOn<ApiController>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .LifestyleTransient() ); } }
3、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>()//如果服务继承了该接口就会自动注册为单例模式,这也就是我们使用ABP时对象自动创建神奇的地方了 .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() ); } }
4、ControllerConventionalRegistrar
/// <summary> /// Registers all MVC Controllers derived from <see cref="Controller"/>. /// </summary> public class ControllerConventionalRegistrar : IConventionalDependencyRegistrar { /// <inheritdoc/> public void RegisterAssembly(IConventionalRegistrationContext context) { context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .BasedOn<Controller>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .LifestyleTransient() ); //PerWebRequest context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .IncludeNonPublicTypes() .BasedOn<IPerWebRequestDependency>() .If(type => !type.GetTypeInfo().IsGenericTypeDefinition) .WithService.Self() .WithService.DefaultInterfaces() .LifestylePerWebRequest() ); } }
5、FluentValidationValidatorRegistrar
public class FluentValidationValidatorRegistrar : IConventionalDependencyRegistrar { public void RegisterAssembly(IConventionalRegistrationContext context) { context.IocManager.IocContainer.Register( Classes.FromAssembly(context.Assembly) .BasedOn(typeof(IValidator<>)).WithService.Base() .LifestyleTransient() ); } }
当我们通过IocContainer调用AddConventionalRegistrar(Assembly assembly)这种方式注册时就会分别调用上面5个方法的RegisterAssembly()从assembly中查找是否有符合要求的对象,如果有就把该对象注册
使用场景如下:
[DependsOn(typeof(AbpWebCommonModule))] public class AbpAspNetCoreModule : AbpModule { public override void PreInitialize() { IocManager.AddConventionalRegistrar(new AbpAspNetCoreConventionalRegistrar());//assembly调用次数由这里决定,如果5中约定注册方式都被添加了,就会查找5次,如果满足条件就注册 IocManager.Register<IAbpAspNetCoreConfiguration, AbpAspNetCoreConfiguration>(); Configuration.ReplaceService<IPrincipalAccessor, AspNetCorePrincipalAccessor>(DependencyLifeStyle.Transient); Configuration.ReplaceService<IAbpAntiForgeryManager, AbpAspNetCoreAntiForgeryManager>(DependencyLifeStyle.Transient); Configuration.ReplaceService<IClientInfoProvider, HttpContextClientInfoProvider>(DependencyLifeStyle.Transient); Configuration.Modules.AbpAspNetCore().FormBodyBindingIgnoredTypes.Add(typeof(IFormFile)); Configuration.MultiTenancy.Resolvers.Add<DomainTenantResolveContributor>(); Configuration.MultiTenancy.Resolvers.Add<HttpHeaderTenantResolveContributor>(); Configuration.MultiTenancy.Resolvers.Add<HttpCookieTenantResolveContributor>(); } public override void Initialize() { IocManager.RegisterAssemblyByConvention(typeof(AbpAspNetCoreModule).GetAssembly());//此方法调用前必须在PreInitialize()中先调用IocManager.AddConventionalRegistrar才会起作用,否则对象不会被依赖注入
} }
一般在模块注入时使用,相信大家经常这样用
那么为什么会执行5次注入呢?请看下面代码:
/// <summary> /// Adds a dependency registrar for conventional registration. /// </summary> /// <param name="registrar">dependency registrar</param> public void AddConventionalRegistrar(IConventionalDependencyRegistrar registrar) { _conventionalRegistrars.Add(registrar);//这个变量是全局变量,用来当做缓存,如果IocManager. AddConventionalRegistrar()在模块中被调用5次约定注册方式,下面的循环就会跑5次 } /// <summary> /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method. /// </summary> /// <param name="assembly">Assembly to register</param> public void RegisterAssemblyByConvention(Assembly assembly) { RegisterAssemblyByConvention(assembly, new ConventionalRegistrationConfig()); } /// <summary> /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method. /// </summary> /// <param name="assembly">Assembly to register</param> /// <param name="config">Additional configuration</param> public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config) { var context = new ConventionalRegistrationContext(assembly, this, config); foreach (var registerer in _conventionalRegistrars)//循环几次由_conventionalRegistrars决定 { registerer.RegisterAssembly(context); } if (config.InstallInstallers) { IocContainer.Install(FromAssembly.Instance(assembly)); } }
这5中约定注册方式是ABP默认的,我们在开发中也可以根据自己的需求扩展自己需要的注入方式
欢迎批评和提建议!
待续.........................................