使用< T>Autofac在Azure Functions启动类中未解析ILogger

kdfy810k  于 2023-02-05  发布在  其他
关注(0)|答案(1)|浏览(158)

在进程版本中解析Azure Function v4的Startup类中的依赖项时,我正在尝试获取ILogger<T>的示例。
只有这样做不起作用,并会导致一个异常,空或不工作的日志记录器。
我遵循了以下AutoFacdocumentation for Azure Functions
我注册了一些类型,并试图解析Startup类中的一个类型。问题出在ILogger<T>上。在本例中是Logger<EventBusServiceBus>
在示例中,我尝试使用ConfigureEventBus方法解析IEventBus,因此,services.AddSingleton<IEventBus, EventBusServiceBus>(sp => ....);尝试使用AddEventBus方法解析。
我不明白为什么因为在Autofac容器中看到一些已注册的类型而无法解析。
请参见代码中的注解。
谢谢!
从文档简化启动:

internal class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        // Use IServiceCollection.Add extension method to add features as needed, e.g.
        //builder.Services.AddDataProtection();

        builder.Services.AddSingleton(GetContainer(builder.Services));

        // Important: Use AddScoped so our Autofac lifetime scope gets disposed
        // when the function finishes executing
        builder.Services.AddScoped<LifetimeScopeWrapper>();

        builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IJobActivator), typeof(AutofacJobActivator)));
        builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IJobActivatorEx), typeof(AutofacJobActivator)));

        builder.Services.AddCustomIntegrations(configuration);
        builder.Services.AddEventBus(configuration);

        var serviceProvider = builder.Services.BuildServiceProvider();
        ConfigureEventBus(serviceProvider);
    }

    private static IContainer GetContainer(IServiceCollection serviceCollection)
    {
        var containerBuilder = new ContainerBuilder();
        containerBuilder.Populate(serviceCollection);
        containerBuilder.RegisterModule<LoggerModule>();

        // This is a convenient way to register all your function classes at once
        containerBuilder.RegisterAssemblyTypes(typeof(Startup).Assembly)
            .InNamespaceOf<Function1>();

        // TODO: Register other dependencies with the ContainerBuilder like normal

        return containerBuilder.Build();
    }

    private void ConfigureEventBus(ServiceProvider sp)
    {
        var eventBus = sp.GetRequiredService<BuildingBlocks.EventBus.Abstractions.IEventBus>();

        // Unable to use eventBus here
    }
}

一些扩展方法:

static class CustomExtensionsMethods
{
    public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<IServiceBusPersisterConnection>(sp =>
        {
            var serviceBusConnectionString = configuration["EventBusConnection"];

            var subscriptionClientName = configuration["SubscriptionClientName"];

            return new DefaultServiceBusPersisterConnection(serviceBusConnectionString);
        });

        return services;
    }

    public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
        {
            var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();

            // Get autofac container so we rolve dependencies from there
            var autoFacContainer = sp.GetRequiredService<IContainer>();

            // This doesn't work
            ////var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();

            // This does work
            var iLifetimeScope = autoFacContainer.Resolve<ILifetimeScope>();

            // This doesn't work
            //var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();

            // This doesn't work either but at least now no error/exception. Resolves into empty logger.
            var loggerFactory = new LoggerFactory();
            var logger = loggerFactory.CreateLogger<EventBusServiceBus>();

            // Tried these for logging without luck.
            // Don't understand because I see a loggerfactory and Ilogger in the container...

            //var loggerFactory = autoFacContainer.ResolveNamed<ILoggerFactory>("loggerFactory");
            //var loggerFactory = autoFacContainer.Resolve<ILoggerFactory>();
            ////var loggerFactory = sp.GetRequiredService<ILoggerFactory>();
            ////var logger = loggerFactory.CreateLogger<EventBusServiceBus>();

            ////autoFacContainer.Resolve<ILogger<EventBusServiceBus>>();

            var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
            string subscriptionName = configuration["SubscriptionClientName"];

            return new EventBusServiceBus(serviceBusPersisterConnection, logger,
                eventBusSubcriptionsManager, iLifetimeScope, subscriptionName);
        });

        services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();

        return services;
    }
}
qacovj5a

qacovj5a1#

所以我现在确实找到了一个可行的解决方案。也许有人有更好的解决方案,但这目前对我有效...

public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
{
    services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
    {
        var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();

        // Get autofac container so we resolve dependencies from there
        var autoFacContainer = sp.GetRequiredService<IContainer>();

        // This does work
        var iLifetimeScope = autoFacContainer.Resolve<ILifetimeScope>();

        // Create a new logger that is connected to the console with a minimum loglevel from host.json based on the namespace
        var loggerFactory = LoggerFactory.Create(builder =>
        {
            var logLevel = configuration.GetValue<LogLevel>("AzureFunctionsJobHost:logging:logLevel:" + typeof(Startup).Namespace, LogLevel.Information);

            builder.AddConsole();
            builder.SetMinimumLevel(logLevel);
        });
        var logger = loggerFactory.CreateLogger<EventBusServiceBus>();

        var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
        string subscriptionName = configuration["SubscriptionClientName"];

        return new EventBusServiceBus(serviceBusPersisterConnection, logger,
            eventBusSubcriptionsManager, iLifetimeScope, subscriptionName);
    });

    return services;
}

所以最重要的是:

// Create a new logger that is connected to the console with a minimum loglevel from host.json based on the namespace
var loggerFactory = LoggerFactory.Create(builder =>
{
    var logLevel = configuration.GetValue<LogLevel>("AzureFunctionsJobHost:logging:logLevel:" + typeof(Startup).Namespace, LogLevel.Information);

    builder.AddConsole();
    builder.SetMinimumLevel(logLevel);
});
var logger = loggerFactory.CreateLogger<EventBusServiceBus>();

相关问题