Asp.net Core依赖注入(Autofac替换IOC容器)

时间:2020-06-17 12:11:35   收藏:0   阅读:100

ASP.NET Core

ASP.NET Core (previously ASP.NET 5) 改变了以前依赖注入框架集成进ASP.NET的方法. 以前, 每个功能 - MVC, Web API, 等. - 都有它自己的 "依赖解析器(dependency resolver)" 机制并且只是‘钩子‘钩住的方式有些轻微的区别. ASP.NET Core 通过 Microsoft.Extensions.DependencyInjection 引入了 conforming container 机制, 包含了请求生命周期作用域, 服务注册等等的统一概念.

在 ASP.NET Core 3.0, 引入了 "generic app hosting" 机制, 它可以应用在非 ASP.NET Core 应用中.

Autofac

中文官网:https://autofaccn.readthedocs.io/

入门

ASP.NET Core 3.0+generic hosting

ASP.NET Core 1.1 - 2.2 使用方法, 你可以调用 WebHostBuilder 的 services.AddAutofac()

在ASP.NET Core 3.0托管方式发生了变化 并且需要不同的集成方式. 你不能在从 ConfigureServices 中返回 IServiceProvider, 也不能再将你的service provider factory加入到service collection.

下面是ASP.NET Core 3+ 和 .NET Core 3+ generic hosting support的集成方式:

Program类

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }

Startup类

添加方法 ConfigureContainer

public void ConfigureContainer(ContainerBuilder builder)
{
    // 在这里添加服务注册
    builder.RegisterType<TopicService>();
}

配置方法命名约定

这意味着你不必使用 Autofac配置在生产环境和开发环境之间切换; 你可以在 Startup 中以编程形式设置.

public void ConfigureDevelopmentContainer(ContainerBuilder builder)
{

}
public void ConfigureProductionContainer(ContainerBuilder builder)
{
    // Add things to the ContainerBuilder that are only for the
    // production environment.
 }

这是ASP.NET Core应用托管的一个功能,它并不是Autofac的行为. ASP.NET Core中的StartupLoader类 是在应用启动时定位调用方法的.

控制器作为服务

默认地, ASP.NET Core 会从容器中解析控制器参数,但不会从中解析控制器 . 这并不是个问题但它意味着:

通过在用service collection注册MVC时指定 AddControllersAsServices() , 你可以改变这个行为. 这么做可以在service provider factory调用 builder.Populate(services) 时自动注册控制器类型到 IServiceCollection.

public void ConfigureServices(IServiceCollection services)
{
    //services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
    
    //或者将Controller加入到Services中,这样写上面的代码就可以省略了
    services.AddControllersWithViews().AddControllersAsServices();
}

如果需要在Controller中使用属性注入,需要在ConfigureContainer中添加如下代码

//如果需要在Controller中使用属性注入,需要在ConfigureContainer中添加如下代码
var controllerBaseType = typeof(ControllerBase);
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
.PropertiesAutowired();

在Controller中使用

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    private readonly TopicService _service;
    private readonly IServiceProvider _provider;
 
    public TopicService Service { get; set; }
 
    public TestController(TopicService service, IServiceProvider provider)
    {
        _service = service;
        _provider = provider;
    }
 
    [HttpGet("{id}")]
    public async Task<Result> GetTopics(int id)
    {            
        // 构造函数注入
        return await _service.LoadWithPosts(id);
    }
 
    [HttpGet("Get/{id}")]
    public async Task<Result> GetTopics2(int id)
    {
        // 属性注入
        return await Service.LoadWithPosts(id);
    }
}

这样就控制器就可以使用服务了。

多租户支持

由于ASP.NET Core想要早早地生成请求生命周期作用域, 这会导致多租户支持无法达到开箱即用的效果. 有时用于识别租户身份的 IHttpContextAccessor , 也无法被及时地构建. Autofac.AspNetCore.Multitenant 包就是用于解决这个问题的.

为了启用多租户支持:

下面是Autofac给的一个示例:

public class Program
{
  public static async Task Main(string[] args)
  {
    var host = Host
      .CreateDefaultBuilder(args)
      .UseServiceProviderFactory(new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
      .ConfigureWebHostDefaults(webHostBuilder => webHostBuilder.UseStartup<Startup>())
      .Build();

    await host.RunAsync();
  }
}

... Startup 类似这样:

public class Startup
{
  // Omitting extra stuff so you can see the important part...
  public void ConfigureServices(IServiceCollection services)
  {
    // This will all go in the ROOT CONTAINER and is NOT TENANT SPECIFIC.
    services.AddMvc();

    // This adds the required middleware to the ROOT CONTAINER and is required for multitenancy to work.
    services.AddAutofacMultitenantRequestServices();
  }

  public void ConfigureContainer(ContainerBuilder builder)
  {
    // This will all go in the ROOT CONTAINER and is NOT TENANT SPECIFIC.
    builder.RegisterType<Dependency>().As<IDependency>();
  }

  public static MultitenantContainer ConfigureMultitenantContainer(IContainer container)
  {
    // This is the MULTITENANT PART. Set up your tenant-specific stuff here.
    var strategy = new MyTenantIdentificationStrategy();
    var mtc = new MultitenantContainer(strategy, container);
    mtc.ConfigureTenant("a", cb => cb.RegisterType<TenantDependency>().As<IDependency>());
    return mtc;
  }
}

有兴趣的朋友可以关注我的微信订阅号,当然也可以关注我的博客,谢谢。
技术分享图片

原文:https://www.cnblogs.com/zhanwei103/p/13151428.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!