使用 DryIoc 替换 Abp 的 DI 框架 (10)

之后再回到最开始的地方,我们最终 AddAbp<TStartupModule>() 方法的内部实现是下面这个样子的:

public static IServiceProvider AddAbp<TStartupModule>(this IServiceCollection services, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null) where TStartupModule : AbpModule { var abpBootstrapper = AddAbpBootstrapper<TStartupModule>(services, optionsAction); ConfigureAspNetCore(services, abpBootstrapper.IocManager); var newContainer = new Container().WithDependencyInjectionAdapter(services); abpBootstrapper.IocManager.InitializeInternalContainer(newContainer); return abpBootstrapper.IocManager.IocContainer.BuildServiceProvider(); }

运行 AspNetCoreApp 项目,我们可以看到正常运行了。

使用 DryIoc 替换 Abp 的 DI 框架

五、存在的问题 5.1 ApplicationService 属性注入失效

在示例项目当中,我在 AspNetCoreApp.Application 库当中建立了一个 TestApplicationService 服务,该服务用有一个 GetJson() 方法。

在其内部,我调用了父类提供的 AbpSession 属性,按照正常的情况下,该属性的实现应该是 ClaimsAbpSession 类型,不过通过测试之后我得到了以下结果:

使用 DryIoc 替换 Abp 的 DI 框架

可以看到,它填充的是默认的空实现,造成这个问题的原因是,DryIoc 本身在注册对象的时候,需要显式提供属性注入的选项,否则默认是不启用属性注入的。

鉴于此,我们为 IIocRegistrar 与 IocManager 内所提供的 Register() 方法增加一个 isAutoInjectProperty 字段,用于判断是否在注册的使用启用属性注入。

public interface IIocRegistrar { /// <summary> /// Registers a type as self registration. /// </summary> /// <typeparam>Type of the class</typeparam> /// <param>Lifestyle of the objects of this type</param> void Register<T>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton,bool isAutoInjectProperty = false) where T : class; /// <summary> /// Registers a type as self registration. /// </summary> /// <param>Type of the class</param> /// <param>Lifestyle of the objects of this type</param> void Register(Type type, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton,bool isAutoInjectProperty = false); /// <summary> /// Registers a type with it's implementation. /// </summary> /// <typeparam>Registering type</typeparam> /// <typeparam>The type that implements <see cref="TType"/></typeparam> /// <param>Lifestyle of the objects of this type</param> void Register<TType, TImpl>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton,bool isAutoInjectProperty = false) where TType : class where TImpl : class, TType; /// <summary> /// Registers a type with it's implementation. /// </summary> /// <param>Type of the class</param> /// <param>The type that implements <paramref/></param> /// <param>Lifestyle of the objects of this type</param> void Register(Type type, Type impl, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton,bool isAutoInjectProperty = false); }

而具体实现则需要使用 isAutoInjectProperty 来判断是否需要属性注入功能,下面随便以一个 Register() 方法为例。

public void Register(Type type, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton,bool isAutoInjectProperty = false) { IocContainer.Register(type, ApplyLifestyle(lifeStyle), made: Made.Of(FactoryMethod.ConstructorWithResolvableArguments, propertiesAndFields: isAutoInjectProperty ? PropertiesAndFields.Auto : null)); RegisterTypeEventHandler?.Invoke(this, type, type); }

写好之后,我们再回到 BasicConventionalRegistrar 注册器当中,因为应用服务类型个都是瞬时对象,并且应用服务都会继承 IApplicationService 接口。所以我们加一个判断,如果是应用服务的话,则在注册的时候,允许进行属性注入。

public class BasicConventionalRegistrar : IConventionalDependencyRegistrar { // ... 其他代码 public void RegisterAssembly(IConventionalRegistrationContext context) { // 瞬时对象注册 var waitRegisterTransient = GetTypes<ITransientDependency>(context.Assembly).ToList(); foreach (var transientType in waitRegisterTransient) { if (typeof(IApplicationService).IsAssignableFrom(transientType.ImplType)) { context.IocManager.Register(transientType.ServiceType,transientType.ImplType,DependencyLifeStyle.Transient,true); continue; } context.IocManager.RegisterIfNot(transientType.ServiceType,transientType.ImplType,DependencyLifeStyle.Transient); } // ... 其他代码 } }

进行了上述更改之后,再次调用接口进行测试可以看到属性已经被正常地注入了。

PS:

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

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