Reputation: 1042
Due to some restrictions on development when using .NET 8, I need to manage some reusable service. Those need to be either transient or singleton, but 1 of 3 service is depend on the rest.
public static IServiceCollection SetupLoggerFactory(this IServiceCollection services)
{
services.AddSingleton<ILoggerFactory>(new LoggerFactory());
return services;
}
public static IServiceCollection SetupKafkaProducerForFoo(this IServiceCollection services, IConfiguration config)
{
services.AddSingleton<IProducerService>(new ProducerService());
return services;
}
The last service
public static IServiceCollection GetAppLogger(this IServiceCollection services, IServiceProvider serviceProvider)
{
services.AddSingleton<IAppLogger<Badboy.Models.LoggingEvent>>
(new LoggerAdapter<Badboy.Models.LoggingEvent>(
serviceProvider.GetService<ILoggerFactory>(), serviceProvider.GetService<IProducerService>()));
return services;
}
I need to pass the Service provider argument, but I don't know how.
The startup.cs
file:
var builder = WebApplication.CreateBuilder(args);
builder.Services.SetupLoggerFactory();
builder.Services.SetupKafkaProducerForFoo(builder.Configuration);
builder.Services.GetAppLogger(missingArg);
Somehow I cannot get the getRequiredService
method, but when I do
var serviceProvider = app.Services;
builder.Services.GetAppLogger(serviceProvider);
it throws an error:
Unhandled exception. System.InvalidOperationException: The service collection cannot be modified because it is read-only.
at Microsoft.Extensions.DependencyInjection.ServiceCollection.ThrowReadOnlyException()
at Microsoft.Extensions.DependencyInjection.ServiceCollection.System.Collections.Generic.ICollection<Microsoft.Extensions.DependencyInjection.ServiceDescriptor>.Add(ServiceDescriptor item)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(IServiceCollection services, Type serviceType, Object implementationInstance)
Upvotes: 0
Views: 52
Reputation: 143098
You can use AddSingleton
accepting lambda:
services.AddSingleton<IAppLogger<Badboy.Models.LoggingEvent>>
(sp => new LoggerAdapter<Badboy.Models.LoggingEvent>(
sp.GetService<ILoggerFactory>(), sp.GetService<IProducerService>()))
So you will not need to pass the service provider to the GetAppLogger
(arguably it should be AddAppLogger
) and you can call it before invoking the builder.Build
which makes the service collection immutable (hence the exception).
Note that based on the provided code just doing:
services.AddSingleton<IAppLogger<Badboy.Models.LoggingEvent>,
LoggerAdapter<Badboy.Models.LoggingEvent>>();
Should also do the trick.
Or using open generic registration:
services.AddSingleton(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
Upvotes: 1