ASP.NET Core3.x Autofac的高级用法汇总

2021-04-03  乐帮网

netcore autofac

.NET Core支持DI(依赖性注射) ,它可以实现设计模式中的控制反转(IoC)在类与其实现之间形成对应。原生、简约的实现已经为Net core中的一部分了。您可以从微软官方网站阅读更多有关它的介绍,在第三方DI框架中对它的支持也很好,对大多数小型项目项目来说,这已经足够好了。作为DI的资深用户,我们也应该掌握最前沿的 Autofac  6 与.Net Core的集成应用。

(1)Autofac的入门

public class Program
{
  public static void Main(string[] args)
  {
    // ASP.NET Core 3.0+:
    // The UseServiceProviderFactory call attaches the
    // Autofac provider to the generic hosting mechanism.
    var host = Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
        .ConfigureWebHostDefaults(webHostBuilder => {
          webHostBuilder
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>();
        })
        .Build();
    host.Run();
  }
}
public class Startup
{
  public Startup(IHostingEnvironment env)
  {
    // In ASP.NET Core 3.0 `env` will be an IWebHostEnvironment, not IHostingEnvironment.
    this.Configuration = new ConfigurationBuilder().Build();
  }
  public IConfigurationRoot Configuration { get; private set; }
  public ILifetimeScope AutofacContainer { get; private set; }
  public void ConfigureServices(IServiceCollection services)
  {
    services.AddOptions();
  }
 
  public void ConfigureContainer(ContainerBuilder builder)
  {
    // Register your own things directly with Autofac here. Don't
    // call builder.Populate(), that happens in AutofacServiceProviderFactory
    // for you.
    builder.RegisterModule(new MyApplicationModule());
  }
 
  public void Configure(
    IApplicationBuilder app,
    ILoggerFactory loggerFactory)
  {
    // If, for some reason, you need a reference to the built container, you
    // can use the convenience extension method GetAutofacRoot.
    this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
    loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();
    app.UseMvc();
  }
}

(2)从assemblies中注册服务

Autofac 可以直接扫描Assembly,然后把类型注册到容器当中。

public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
        .AsClosedTypesOf(typeof(IConfigureOptions<>));
 }

这将注册给定类型的具体实现。 在这种情况下,它将注册IConfigureOptions <>的所有实现。 有关如何使用依赖项注入配置设置的更多信息,请参见选项模式。

(3)在Autofac中使用Mvc / Api控制器实例化

我们无法从容器中解析出控制器; 只能生成控制器中构造函数的参数。 这意味着在控制器的生命周期中,属性注入等不由Autofac管理,而是由ASP.NET Core管理。 您可以使用AddControllersAsServices()进行更改。

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

public void ConfigureContainer(ContainerBuilder builder) {
     
    var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes().Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
    builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
}

在这里,我们注册所有类型的控制器基础类型的父类,也就是处自定义Contoller类。我们还启用属性注入功能(第 5 行)。当您想要在基础控制器实现中拥有一些可以重复使用的属性时,这很有用。

(4)使用Autofac 注册 EF Core DbContext 

如果使用Entity Framework Core,则希望DbContext由DI容器管理。 一个重要的注意事项是DbContext应该作为一个工作单元运行,并且可以请求生存期。 在本机DI中,它注册为范围服务,在Autofac中等于InstancePerLifetimeScope。

public static void AddCustomDbContext(this ContainerBuilder builder, IConfiguration configuration) {
    builder.Register(c => {
        var options = new DbContextOptionsBuilder<ApplicationContext>();
        options.UseLoggerFactory(c.Resolve<ILoggerFactory>()).EnableSensitiveDataLogging();
        options.UseSqlServer(configuration["ConnectionStrings:ApplicationDb"], sqlOptions => { sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
            sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
        });
        return options.Options;
    }).InstancePerLifetimeScope();
    builder.RegisterType<ApplicationContext>()
          .AsSelf()
          .InstancePerLifetimeScope();
}
public void ConfigureContainer(ContainerBuilder builder) {
     
    builder.AddCustomDbContext(this.Configuration);
}

(5)使用  modules来注册

public void ConfigureContainer(ContainerBuilder builder) {
     
    builder.RegisterModule(new MediatorModule());
    builder.RegisterModule(new ApplicationModule());
}
public class ApplicationModule: Autofac.Module {
    public ApplicationModule() {}
    protected override void Load(ContainerBuilder builder) {
        builder.RegisterType<NinjaService>().As<INinjaService>().SingleInstance();
        builder.RegisterType<KatanaService>().As<IKatanaService>().InstancePerLifetimeScope();
     
        builder.RegisterAssemblyTypes(typeof(Startup).GetTypeInfo().Assembly).AsClosedTypesOf(typeof(INinjaRepository<>)).InstancePerLifetimeScope();
    }
}

在模块中或以按照你项目的结构来注册你的实例。

原文:https://danylomeister.blog/2021/01/31/tips-on-using-autofac-in-net-core-3-x/

公众号二维码

关注我的微信公众号
在公众号里留言交流
投稿邮箱:1052839972@qq.com

庭院深深深几许?杨柳堆烟,帘幕无重数。
玉勒雕鞍游冶处,楼高不见章台路。
雨横风狂三月暮。门掩黄昏,无计留春住。
泪眼问花花不语,乱红飞过秋千去。

欧阳修

付款二维码

如果感觉对您有帮助
欢迎向作者提供捐赠
这将是创作的最大动力