6

按照 AutoFac 文档,我能够在 ASP.NET Core 3.0 Preview 3 中使用 AutoFac。ASP.NET Core 3.0 Preview 4 和 ASP.NET Core 3.0 Preview 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'.

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

启动.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);
}

应用程序模块.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();
}
4

1 回答 1

9

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

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

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
      .UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<--NOTE THIS
      .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();
    });

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

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自动为您创建,因此您只需注册即可。

其中一些直接取自Asp.Net Core的Autofac 文档

于 2019-05-30T21:19:49.800 回答