Asp.NET Ядро с ошибкой регистрации экземпляра SimpleInjector

#c# #asp.net-core #asp.net-core-mvc #simple-injector

#c# #asp.net-ядро #asp.net-core-mvc #простой инжектор

Вопрос:

Я пытаюсь написать AspNet Api с использованием SimpleInjector. Однако у меня возникли проблемы с SimpleInjector. Когда я запускаю приложение AspNet после регистрации типа в контейнере, я получаю эту ошибку:

Необработанное исключение. Система.Исключение AggregateException: некоторые службы не могут быть сконструированы (ошибка при проверке дескриптора сервиса ‘ServiceType: Web.Services.Время жизни WeatherForecastController: переходный тип реализации: Web.Services.WeatherForecastController’: не удалось разрешить службу для типа ‘MediatR.IMediator’ при попытке активировать ‘Web.Services.WeatherForecastController’.) —> Система.Исключение InvalidOperationException: ошибка при проверке дескриптора сервиса ‘ServiceType: Web.Services.Время жизни WeatherForecastController: переходный тип реализации: Web.Services.WeatherForecastController’: не удалось разрешить службу для типа ‘MediatR.IMediator’ при попытке активировать ‘Web.Services.WeatherForecastController’. —> Система.Исключение InvalidOperationException: не удалось разрешить службу для типа ‘MediatR.IMediator’ при попытке активировать ‘Web.Services.WeatherForecastController’. в Microsoft.Расширения.DependencyInjection.ServiceLookup.Вызывает объект-объект.CreateArgumentCallSites(тип ServiceType, Тип implementationType, CallSiteChain callSiteChain, ParameterInfo[] параметры, логическое значение throwIfCallSiteNotFound)

Я понимаю, что в контейнере отсутствует тип, не зарегистрированный, однако я регистрирую посредника непосредственно перед созданием экземпляра сервера Aspnet

  public class Program
    {
        public static async Task Main(string[] args)
        {
            var configuration = LoadConfiguration(args);
            var comp = new AspNetComponent(args);
            var container = new Container();
            container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
            container.Options.DefaultLifestyle = Lifestyle.Scoped;
            DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
            container.Register<IMediator, Mediator>();
            comp.Configure(configuration, container);
            await comp.StartAsync(CancellationToken.None);
        }
 

В AspNetComponent.cs:

  public static IHostBuilder CreateHostBuilder(
      string[] args, IConfiguration configuration, Container container)
        {
            Startup.UseContainer(container);
            return Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                    webBuilder.UseUrls("https://0.0.0.0:8080");
                });
        }
 

И мой класс Startup.cs:

  public class Startup
    {
        private static Container _container;

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        internal static void UseContainer(Container container)
        {
            _container = container;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc()
                .AddApplicationPart(
                    Assembly.GetAssembly(typeof(WeatherForecastController)))
                .AddControllersAsServices();

            services.AddSimpleInjector(_container, options =>
            {
                options.AddAspNetCore()
                    .AddControllerActivation();
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseSimpleInjector(_container);
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
        }
 

Я понятия не имею, в чем проблема, я отлаживал почти 3 дня.

Комментарии:

1. Я не могу воспроизвести вашу проблему. Я советую создать новый веб-проект, используя шаблон VS по умолчанию, и добавить интеграцию Simple Injector, как описано в документации . Когда это сработает, добавляйте необходимые функции шаг за шагом, пока они не сломаются.

Ответ №1:

Я думаю, что ваш код регистрирует контроллеры дважды (один раз в контейнере по умолчанию и второй раз внутри .AddSimpleInjector ). Контейнер по умолчанию идет первым, и он не Mediatr зарегистрирован (мы сделали это только в контейнере SimpleInjector), поэтому при создании контроллера происходит сбой — он не может разрешить IMediatr. Просто удалите первый случай регистрации контроллеров.

 public void ConfigureServices(IServiceCollection services)
{
    // comment out first registration of services
    // we keep services.AddMvc() because it is required for simple injector container AddAspNetCore()
    services.AddMvc()
        .AddApplicationPart(Assembly.GetAssembly(typeof(WeatherForecastController)));
        //.AddControllersAsServices();

    // you are doing this in Program.cs
    var container = new Container();

    services.AddSimpleInjector(container, x =>
    {
        x.AddAspNetCore()
            .AddControllerActivation();
        // you are doing this in Program.cs
        x.Container.BuildMediator(Assembly.GetExecutingAssembly());
    });
}
 

Комментарии:

1. Я отменяю первую часть (удаляя AddApplicationPart), но для BuildMediator он не может найти метод? Я предполагаю, что это метод расширения, но я не могу найти пакет?

2. И где мне зарегистрировать контроллеры ?

3. вы уже регистрируете контроллеры в своем коде в simple injector ( AddControllerActivation ). И вам не нужен BuildMediator метод, поскольку ваш регистр <IMediator, Mediator> для контейнера снаружи

4. Хорошо, теперь я понимаю. Однако контроллер находится в другой сборке, поэтому URL-адрес всегда не найден. Как я могу зарегистрировать контроллеры из другой сборки?

5. только что протестировано, похоже, что единственная строка, которую вам нужно закомментировать, это .AddControllersAsServices() . .AddApplicationPart(Assembly.GetAssembly(typeof(WeatherForecastController))) может остаться. SimpleInjector использует тот же механизм для обнаружения контроллера. Соответствующим образом обновил мой asnwer