Настройте AutoFac в ASP.NET Core 3.0 Preview 5 или более поздней версии. - PullRequest
1 голос
/ 30 мая 2019

Следуя документации AutoFac, я смог использовать AutoFac в ASP.NET Core 3.0 Preview 3. В 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 (аргументы) -> Host.CreateDefaultBuilder (аргументы)

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 Ответ

2 голосов
/ 31 мая 2019

Необходимо внести несколько изменений, чтобы соответствовать новому синтаксису

. Вам необходимо подключить фабрику поставщика услуг для 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 для Asp.Net Core

...