在ASP.NET Core 3.0 Preview 5或更高版本中配置AutoFac

时间:2019-05-30 20:35:11

标签: asp.net autofac autofac-configuration

按照AutoFac文档,我能够在ASP.NET Core 3.0 Preview 3中使用AutoFac。 ASP.NET Core 3.0预览版4和ASP.NET Core 3.0预览版5引入了重大更改,并且AutoFac不再起作用。 我的控制器方法返回运行时错误。

在我的代码中,ASP.NET Core 3.0 Preview 3和ASP.NET Core 3.0 Preview 5之间的区别如下:

IWebHostBuilder-> IHostBuilder

CreateWebHostBuilder-> CreateHostBuilder

WebHost.CreateDefaultBuilder(args)-> Host.CreateDefaultBuilder(args)

public IServiceProvider ConfigureServices(IServiceCollection services)

public void ConfigureServices(IServiceCollection services)
System.AggregateException
  HResult=0x80131500
  Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: API.Controllers.CityController Lifetime: Transient ImplementationType: CityController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'CityController'.) (Error while validating the service descriptor 'ServiceType: LocationController Lifetime: Transient ImplementationType: LocationController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'LocationController'.) (Error while validating the service descriptor 'ServiceType: PersonController Lifetime: Transient ImplementationType: PersonController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'PersonController'.) (Error while validating the service descriptor 'ServiceType: SchoolController Lifetime: Transient ImplementationType: SchoolController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'SchoolController'.) (Error while validating the service descriptor 'ServiceType: TestParentController Lifetime: Transient ImplementationType: TestParentController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'TestParentController'.) (Error while validating the service descriptor 'ServiceType: TypeController Lifetime: Transient ImplementationType: TypeController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'TypeController'.)
  Source=Microsoft.Extensions.DependencyInjection
  StackTrace:
   at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at API.Program.Main(String[] args) in C:\Projects\FirstResponse\API\Program.cs:line 13

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: CityController Lifetime: Transient ImplementationType: CityController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'CityController'.

Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'CityController'.

Program.cs

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
      webBuilder
        .UseStartup<Startup>()
        .ConfigureLogging((hostingContext, builder) =>
        {
          builder.ClearProviders();
          builder.SetMinimumLevel(LogLevel.Trace);
          builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
          builder.AddConsole();
          builder.AddDebug();
        })
        .UseNLog();
    });

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
  services
    .AddCustomOptions(Configuration)
    .AddCors()
    .AddJwtAuthentication()
    .AddHttpClients()
    .AddCustomMVC()
    .AddIIS()
    .AddCaching()
    .AddCustomDbContext(Configuration, Environment)
    .AddSwagger()
    .AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies())
    .AddHealthChecksUI();

  var serviceProvider = services.BuildServiceProvider();

  _appSettings = serviceProvider.GetService<IOptionsSnapshot<AppSettings>>().Value;

  var connectionString = Configuration.GetConnectionString(nameof(FirstResponseContext));

  // Create a Autofac container builder
  var builder = new ContainerBuilder();

  // Read service collection to Autofac
  builder.Populate(services);

  // Use and configure Autofac
  builder.RegisterModule(new MediatorModule());
  builder.RegisterModule(new ApplicationModule(connectionString));

  // build the Autofac container
  ApplicationContainer = builder.Build();

  // creating the IServiceProvider out of the Autofac container
  //return new AutofacServiceProvider(ApplicationContainer);
}

ApplicationModule.cs

protected override void Load(ContainerBuilder builder)
{
  builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
  builder.RegisterType<ModelValidationAttribute>().InstancePerLifetimeScope();
  builder.RegisterType<ETagCache>().InstancePerLifetimeScope();

  builder.RegisterType<FirstResponseContext>().As<DbContext>().As<IUnitOfWork>().InstancePerLifetimeScope();
}

1 个答案:

答案 0 :(得分:1)

需要进行一些更改以符合新语法

您需要为AutoFac插入服务提供商工厂

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder => {
          webBuilder
            .ConfigureServices(services => services.AddAutofac()) //<--NOTE THIS
            .UseStartup<Startup>()
            .ConfigureLogging((hostingContext, builder) => {
                builder.ClearProviders();
                builder.SetMinimumLevel(LogLevel.Trace);
                builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                builder.AddConsole();
                builder.AddDebug();
            })
            .UseNLog();
    });

然后在您的ConfigureContainer类的Startup方法中,将内容直接注册到Autofac ContainerBuilder中。

public IConfigurationRoot Configuration { get; private set; }

public void ConfigureServices(IServiceCollection services) {
    services
        .AddCustomOptions(Configuration)
        .AddCors()
        .AddJwtAuthentication()
        .AddHttpClients()
        .AddCustomMVC()
        .AddIIS()
        .AddCaching()
        .AddCustomDbContext(Configuration, Environment)
        .AddSwagger()
        .AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies())
        .AddHealthChecksUI();    
}

public void ConfigureContainer(ContainerBuilder builder) {
   var connectionString = Configuration.GetConnectionString(nameof(FirstResponseContext));

    // Use and configure Autofac
    builder.RegisterModule(new MediatorModule());
    builder.RegisterModule(new ApplicationModule(connectionString));
}

IServiceProvider将自动为您创建,因此您无需进行任何注册即可。

其中一些是直接从Autofac documentation中获取的Asp.Net Core