zoukankan      html  css  js  c++  java
  • Asp.net Core依赖注入(Autofac替换IOC容器)

    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/

    入门

    • Nuget引入 Autofac.Extensions.DependencyInjection 包.
    • 在你的 Program.Main 方法内, 将Autofac附加给托管机制.(见下例)
    • 在 Startup 类的 ConfigureServices 方法中用其他库提供的扩展方法注册东西到 IServiceCollection .
    • 在 Startup 类的 ConfigureContainer 方法中直接注册东西到Autofac ContainerBuilder.
    • IServiceProvider 会自动替你创建, 因此你无需做任何事只要 注册东西 即可.

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

    配置方法命名约定

    • Configure, ConfigureServices, 和 ConfigureContainer 方法都支持基于你应用中 IHostingEnvironment.EnvironmentName 参数的环境特定命名约定. 默认地, 名称为 Configure, ConfigureServices, 和 ConfigureContainer.
    • 如果你想要环境特定设置, 你可以把环境名称放在 Configure 部分后面, 类似 ConfigureDevelopment, ConfigureDevelopmentServices, 和 ConfigureDevelopmentContainer. 如果方法并不以匹配的环境名称显示, 它会回到默认方法.

    这意味着你不必使用 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.AspNetCore.Multitenant NuGet包引用.
    • 在 Program.Main 中构建web host时调用 UseServiceProviderFactory 和 AutofacMultitenantServiceProviderFactory. 提供一个配置租户的回调.
    • 在 Startup.ConfigureServices 和 Startup.ConfigureContainer 中注册进入 根容器(root container) 的东西(那些非租户特有的).
    • 在回调中 (如Startup.ConfigureMultitenantContainer) 构建你的多租户容器.

    下面是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;
      }
    }
    

  • 相关阅读:
    StatusStrip控件的使用(转:http://blog.sina.com.cn/s/blog_4f18c3ec0100fguf.html)
    linux根文件系统
    git使用技巧
    修改git用户名
    luci中添加application
    openwrt安装依赖库
    STM32(二十九)定时器介绍
    openwrt部分文件解析
    uci.js文件解析
    矿机算力
  • 原文地址:https://www.cnblogs.com/zhanwei103/p/13151428.html
Copyright © 2011-2022 走看看