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>();

 

posted @ 2019-01-23 19:36  几清  阅读(892)  评论(0编辑  收藏  举报