其他分享
首页 > 其他分享> > ABP.vNext系列之Dependency Injection

ABP.vNext系列之Dependency Injection

作者:互联网

概念

  ABP.vNext 是一个 ASP.NET Core的开源WEB应用程序框架,关于它的相关介绍可以查看官网(ABP Framework - Open Source Web Application Framework),本系列不过多赘述。

注入方式

  ABP.vNext 的 Dependency Injection 是基于Microsoft dependency injection extension 库 (Microsoft.Extensions.DependencyInjection)来实现的。由于ABP的核心是模块化设计,每一个模块都定义了自己的服务注册类,所以你需要在你定义的模块中,重写 AbpModule 中的 ConfigureServices 方法。

  ABP.vNext 采用约定配置的方式来实现依赖注入。在默认情况下,某些特定类型已注册到依赖注入容器中了,包括:

​ 除了以上默认情况下的特定类型会自动注册到DI容器中,你还可以通过实现ITransientDependencyISingletonDependencyIScopedDependency接口来实现自动注入,如以下代码将TaxCalculator注册成为生命周期为transient的服务。

public class TaxCalculator : ITransientDependency
{
}

  ABP还提供了 Attribute的方式来实现依赖注入,你可以通过添加 DependencyAttribute 特性来实现,该特性有三个属性

[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
public class TaxCalculator
{

}

  需要注意的是,如果使用 DenpendencyAttribute 设置了 Lifetime,其优先级高于其他注入方式。

  当一个服务同时实现了不同的接口时,可以使用 ExposeServicesAttribute 特性来暴露该服务注入时使用的是哪个接口。如果你不指定公开哪个接口,ABP 将采用命名约定的方式进行公开,下面的代码中,ICalculator, ITaxCalculator 就属于默认的命名约定。

[ExposeServices(typeof(ITaxCalculator))]
public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency
{

}

  除了上述的注入方式,ABP.vNext 还保留了手动注册的方式。

public class BlogModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        //Register an instance as singleton
        context.Services.AddSingleton<TaxCalculator>(new TaxCalculator(taxRatio: 0.18));

        //Register a factory method that resolves from IServiceProvider
        context.Services.AddScoped<ITaxCalculator>(
            sp => sp.GetRequiredService<TaxCalculator>()
        );
    }
}

  如果需要替换已经存在的服务时,你除了使用 DependencyAttribute 指定 ReplaceServicestrue之外,还可以使用 Microsoft Dependency Injection库中的 IServiceCollection.Replace方法来实现。

public class MyModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        //Replacing the IConnectionStringResolver service
        context.Services.Replace(ServiceDescriptor.Transient<IConnectionStringResolver, MyConnectionStringResolver>());
    }
}

使用方式

构造函数注入

public class TaxAppService : ApplicationService
{
    private readonly ITaxCalculator _taxCalculator;

    public TaxAppService(ITaxCalculator taxCalculator)
    {
        _taxCalculator = taxCalculator;
    }

    public void DoSomething()
    {
        //...use _taxCalculator...
    }
}

属性注入,Asp.NET Core自带的依赖注入并不支持属性注入,ABP.vNext中使用 Autofac来实现。

public class MyService : ITransientDependency
{
    public ILogger<MyService> Logger { get; set; }

    public MyService()
    {
        Logger = NullLogger<MyService>.Instance;
    }

    public void DoSomething()
    {
        //...use Logger to write logs...
    }
}

通过IServiceProvider获取

public class MyService : ITransientDependency
{
    private readonly IServiceProvider _serviceProvider;

    public MyService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public void DoSomething()
    {
        var taxCalculator = _serviceProvider.GetService<ITaxCalculator>();
        //...
    }
}

​ 当一个接口被多个实现类实现时,使用时将会获取到最后一个注册的实现类。除非使用 IEnumerable<Interface> 去获取所有的实现类。

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services.AddTransient<IExternalLogger, ElasticsearchExternalLogger>();
    context.Services.AddTransient<IExternalLogger, AzureExternalLogger>();
}
public class MyService : ITransientDependency
{
    private readonly IEnumerable<IExternalLogger> _externalLoggers;

    public MyService(IEnumerable<IExternalLogger> externalLoggers)
    {
        _externalLoggers = externalLoggers;
    }

    public async Task DemoAsync()
    {
        foreach (var externalLogger in _externalLoggers)
        {
            await externalLogger.LogAsync("Example log message...");
        }
    }
}

​ 或许某些时候,你需要监听某些服务被注册时的行为,这时候可以使用 IServiceCollection.OnRegistred Event 来实现

public class AppModule : AbpModule
{
    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.OnRegistred(ctx =>
        {
            if (ctx.ImplementationType.IsDefined(typeof(MyLogAttribute), true))
            {
                ctx.Interceptors.TryAdd<MyLogInterceptor>();
            }
        });
    }
}

标签:vNext,默认,class,ABP,context,Injection,public,注入
来源: https://www.cnblogs.com/jesen1315/p/16194762.html