二、.Net Core 依赖注入详解及Autofac使用(DI推荐实践方式)

 上一篇介绍了依赖注入容器在复杂场景下的使用,这一篇主要介绍推荐的实践用法,以及如何注入和使用第三方容器。

1. 推荐实践

Action 注入依赖service

在Controller中,我们习惯于将所有需要的一股脑的注入到controller的constrcutor中,但实际上,有些service,我们只在个别的Action方法中用到,这样的service注入在了constrcutor中,会导致每次请求的时候都实例化一次这个service,哪怕并不需要。对于这样的service,推荐的做法是在Action 方法中声明通过依赖注入容器帮助我们实例化出来。

示例:

    [Route("api/[controller]")]
    [ApiController]
    public class CurrentWeatherController : ControllerBase
    {
        private readonly IMemoryCache _memoryCache;

        public CurrentWeatherController(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        [Route("A")]
        public Get() {
            // 业务逻辑
        }
    
        [Route("B")]
        public Get([FromServices] IBservice bservice) {
            // 业务逻辑 只在此 路由中使用 bservice
        }
    }                

 

 

 

Middleware 注入依赖service

middleware是在host主机启动时候就已经实例化好的,因此对于一些非singleton得service,如果将那些service注入到middleware得依赖方法中,就会导致middleware捕获一些scope和transient生命周期得service,进而造成不可预测的风险。

对于非singleton 得service,在middleware得注入方法推荐:

services.AddScoped<IUserManager, UserManager>();

------------------------------------

public class LastRequestMiddleware
    {
        private readonly RequestDelegate _next;

        public LastRequestMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context, UserManager userManager)
        {
            // 业务逻辑

            await _next(context);
        }
    }

 

使用依赖注入替代GetService

不推荐得做法

  

推荐使用方式

public class MyClass
{
    private readonly IOptionsMonitor<MyOptions> _optionsMonitor;

    public MyClass(IOptionsMonitor<MyOptions> optionsMonitor)
    {
        _optionsMonitor = optionsMonitor;
    }

    public void MyMethod()
    {
        var option = _optionsMonitor.CurrentValue.Option;

        ...
    }
}

 

2. Autofac 集成及使用场景

不同版本的autofac集成参考  https://autofac.readthedocs.io/ 官网

这里以.net core3+ 为例,因为通用主机概念的引入,在3.0+的版本引入autofac和以前有一些不同。通过  UseServiceProviderFactory 来注入 AutofacServiceProviderFactory 。

 var host = Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
        .ConfigureWebHostDefaults(webHostBuilder => {
          webHostBuilder
            .UseStartup<Startup>();
        })
        .Build();

在startup.cs 中,和默认的container类似,autofac有一个 ConfigureContainer 的方法,允许你在这个方法内部注册你的services。

public void ConfigureServices(IServiceCollection services)
  {
    services.AddOptions();
  }

  public void ConfigureContainer(ContainerBuilder builder)
  {
    
    builder.RegisterModule(new MyApplicationModule());
  }
    
......... 

 

具体的使用方法放在下一篇中,因为autofac的功能确实很强大,这里进行一下抛砖引玉,autofac可以做哪些?

1. 更宽泛的生命周期管理,它可以指定scope的name来保证service在该scope里共享实例;

2. module的注册方式及声明式的注册;相比于默认的DI container, 它支持json的声明方式及assembly的加载,减少了频繁添加修改service的注册信息的工作;

3. 自动的属性注入;

4. autofac 实现面向切片编程; (有助于我们将通用的处理逻辑和业务逻辑相分离,当然也不要滥用,对于一些通过filterattribute, authorazition attibute本身可以实现的,不需要为了使用而使用)。

下一篇会重点关注这个autofac的实际开发应用场景,并且区分什么时候应该使用。

 

------------------------

正如大佬们所说“我只是一个小学生”, 欢迎大家讨论交流,指出不足以进步更好,谢谢!

posted @ 2021-07-08 13:12  懒懒的佩奇  阅读(392)  评论(0编辑  收藏  举报