0

I have a controller with the following content (simplified version):

        [HttpPost]
        public Task<OkResult> Post([FromBody] commonRequest)
        {
            parser.DoWork(commonRequest);

            return Ok();
        }

The commonRequest object is populated from the incoming JSON request. The parser.DoWork method should invoke the creation of a new instance of the class, depending on requestBody. Here's what it looks like:

    public class CommonParser : ICommonParser
    {
        private readonly ILogger<CommonParser> logger;
        private IServiceProvider serviceProvider;

        public CommonParser(ILogger<CommonParser> _logger, IServiceProvider _serviceProvider)
        {
            this.logger = _logger;
            this.serviceProvider = _serviceProvider;
        }

        public void DoWork(CommonRequest commonRequest)
        {
            ICommonParser parser = (ICommonParser)Activator.CreateInstance(Type.GetType(commonRequest.instance)
                                        , serviceProvider);
            parser.DoWork(commonRequest);

        }
    }

I have three classes whose names are passed through commonRequest.instance. All of these classes implement the ICommonParser interface. Inside these classes, I pass a serviceProvider so that they can get the ILogger inside themselves and use it. Here is an example constructor of this class:

        private readonly ILogger<Parser1> logger;

        public Parser1(IServiceProvider serviceProvider)
        {
            this.logger = serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<Parser1>();
        }

As a result, I can send only one message in this way. On the second call, I get a message that serviceProvider.GetRequiredServiceILoggerFactory () has been destroyed. Please tell me what to do in such cases. I think I'm designing wrong.

Grigory
  • 3
  • 1

1 Answers1

0

From Dependency Injection in ASP.NET Core:

Avoid using the service locator pattern. For example, don't invoke GetService or GetRequiredService to obtain a service instance when you can use DI instead.

1) register the logger factory or the logger service, in case of the logger factory

services.AddSingleton<ILoggerFactory, LoggerFactory>();

2) use constructor injection to inject logger factory into the constructor

public Parser1(ILoggerFactory loggerFactory)
{
}

3) you might create a new interface for the parsers (parser1, 2, 3). The parsers implement this interface. Register them as services

public interface IParser
{
    void DoWork(CommonRequest commonRequest);
}

services.AddTransient<Parser1>(); // implements IParser
services.AddTransient<Parser2>(); 

This post gives an answer how to resolve classes implementing the same interface. For getting parser with DI you will actually need IServiceProvider:

_serviceProvider.GetService<Parser1>();
Martin Staufcik
  • 8,295
  • 4
  • 44
  • 63