Search code examples
c#asp.net-coreasp.net-web-apidependency-injectionextension-methods

How to create own ServiceCollectionExtension and pass dependencies as parameters in ASP.net Core c#


I try to create my own ServiceCollectionExtension for the my service 'FdmMediator'.

I want to register the service 'FdmMediator' as a singleton, and I need to pass some parameters. The parameters are also injected in the container earlier.

The parameters, needed to create the 'FdmMediator', are an ILoggerFactory, settings loaded from appsetting.json and a repository.

I use serilog as application logger, and I save the application setting from the appsetting.json as an IOption<GlobalSettings>.

// Logger
Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration)
    .CreateLogger();

builder.Logging.AddSerilog();

// application settings
builder.Services.Configure<GlobalSettings>(builder.Configuration.GetSection("ApplicationSettings"));

// Where I want to use my extensions
builder.Services.AddFdmMediator()

// Other code...

var app = builder.Build();

// ...

Later in the code I register my repository in the container builder.Services.AddTransient<IApplicationTraceRepository, ApplicationTraceRepository>();

To create a new instance of the FdmMediator-Class I need to pass the registered parameters.

public class FdmMediator
{

    private readonly ILogger _logger;
    private readonly IApplicationTraceRepository _errorRepository;
    private readonly GlobalSettings _settings;

    public FdmMediator(ILogger logger, IApplicationTraceRepository errorRepository, IOptions<GlobalSettings> s)
    {
        _logger = logger;
        _errorRepository = errorRepository;
        _settings = s.Value;
    }
}

In my IServiceCollection extension I want to create a new logger based on the serilog logger configured in the programm.cs.

 public static class FdmMediatorBuilderExtensions
 {

     public static IServiceCollection AddFdmMediator(this IServiceCollection services, ILoggerFactory factory, IApplicationTraceRepository rep, IOptions<GlobalSettings> settings)
     {
         // Create Mediator
         // The logger factory should create a new serilog-logger based on the same settings as configured in the programm.cs
         var l = factory.CreateLogger(nameof(FdmMediator));

         var m = new FdmMediator(l, rep, settings);

         // Add as singleton
         services.AddSingleton<FdmMediator>(m);

         return services;
         
     }
 }

What should I do to get the parameters from the container and pass them, to create my 'FdmMediator' as a singleton ? And how can I get a ILoggerFactory from my Serilogger created earlier.


Solution

  • There's no need for an extension method in this case. All the constructor parameters are already registered. The only problem is that the type of the logger dependency is ILogger instead of ILogger<FdmMediator>. The documentation of ILogger explains that :

    the category name is derived from the specified TCategoryName type name

    If you change the constructor signature to this:

    public FdmMediator(ILogger<FdmMediator> logger, 
                       IApplicationTraceRepository errorRepository, 
                       IOptions<GlobalSettings> s)
    

    You should be able to register the class with just :

    services.AddSingleton<FdmMediator>();