如何在模块的构造函数中使用 IServiceProvider 参数注册 Autofac 模块

问题描述 投票:0回答:0

程序.cs:

var config = GetConfiguration();

var host = CreateHostBuilder(config, args).Build();

host.Run();

return 0;

IConfiguration GetConfiguration()
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();

    return builder.Build();
}

IHostBuilder CreateHostBuilder(IConfiguration configuration, string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
        .ConfigureAppConfiguration(x => x.AddConfiguration(configuration))
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
            webBuilder.UseContentRoot(Directory.GetCurrentDirectory());
        });

Sturtup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services
       .AddCustomMvc(Configuration)
       .AddSwaggerGen()
       .AddCustomDbContext(Configuration);
}

public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterModule(new ApplicationModule(Configuration.GetConnectionString("mssql")!));
    builder.RegisterModule(new MetiatorModule());

    builder.RegisterModule(new DomainEventMediatorModule(<IServiceCollection or IServiceProvider should be here>));
}
public class DomainEventMediatorModule
    : Autofac.Module
{
    public static IServiceScopeFactory? ServiceScopeFactory { get; set; }

    protected override void Load(ContainerBuilder builder)
    {
        Func<DomainEventMediator> domainEventMediatorCreation = () =>
        {
            DomainEventMediator domainEventMediator = new();
            var domainEventHandlerTypes = Assembly
                .GetAssembly(typeof(UserCreatedDomainEventHandler))!
                .GetTypes()
                .Where(x => x.GetInterfaces()
                    .Any(y => y.IsGenericType
                           && y.GetGenericTypeDefinition() == typeof(IDomainEventHandler<>)));

            using (var scope = ServiceScopeFactory?.CreateScope())
            {
                foreach (var handlerType in domainEventHandlerTypes)
                {
                    var domainEventType = handlerType
                        .GetInterfaces()
                        .First()
                        .GetGenericArguments()
                        .First();
                    var registereMethod = typeof(DomainEventMediator)
                        .GetMethod(nameof(DomainEventMediator.Register))!
                        .MakeGenericMethod(domainEventType!);

                    var handlerInstance = ActivatorUtilities.CreateInstance(scope!.ServiceProvider, handlerType)!; // StackOverflowException here

                    registereMethod.Invoke(domainEventMediator, new object[] { handlerInstance });
                }
            }
            
            return domainEventMediator;
        };

        builder.Register(c => domainEventMediatorCreation())
            .As<IDomainEventMediator>()
            .SingleInstance();
    }
}

我需要将服务或服务提供商作为参数发送给 DomainEventMediatorModule 构造函数,但是,我需要来自 ApplicationModule 模块的依赖项。

那么,我怎样才能获得包含所有需要的服务的 ServiceCollection 或 ServiceProvider?

我尝试从 ConfigureServices 方法获取服务,但它没有来自模块的服务。 此外,我无法在 ConfigureContainer 方法中调用

builder.Build()
,因为 Autofac 在执行此方法后第二次调用它。

c# .net-core dependency-injection autofac autofac-module
© www.soinside.com 2019 - 2024. All rights reserved.