I'm trying to get instance of ILogger<T>
when resolving a dependency in the Startup
class of an Azure Function v4 in process version.
Only this doesn't work and will result in an exception, null or a not working logger.
I followed the following AutoFac
documentation for Azure Functions.
I register some types and try to resolve a type in the Startup
class. The problem is the ILogger<T>
. In this case the Logger<EventBusServiceBus>
.
In the sample I try to resolve IEventBus
in the ConfigureEventBus
method. Because of this, services.AddSingleton<IEventBus, EventBusServiceBus>(sp => ....);
is trying to be resolved in the AddEventBus
method.
I don't understand why it can't be resolved because I see some registered types in the Autofac container.
See the comments in the code.
Thanks!
Simplified Startup from the docs:
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
}
}
Some extension methods:
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;
}
}