Home > OS >  C# - How to inject new instance of dependency to a class which get instantiated once in the app life
C# - How to inject new instance of dependency to a class which get instantiated once in the app life

Time:01-10

Here is a class which will be instantiated only once through out the lifetime of the application

public class SampleClass //instantiated only once
 {
  public void DoOpertation()//will be called by every incoming request
   {
     var dependentService = new SampleService();
     //do operation on dependentService instance
     ....
   }
  }

Method "DoOpertation" operation will be called many time during the application lifetime.

In "DoOpertation" method I'm instantiating 'SampleService' using 'new' keyword which I don't want to do for the below reasons

  1. It breaks single responsibility principle (SRP) as creating SampleService class instance is not SampleClass's responsibility
  2. Create tight coupling between SampleClass & SampleService classes which makes unit testing harder atleast

I can't use DI container for constructor injection of dependencies as SampleClass get instantiated only once in the application lifetime but where as every invocation of DoOpertation method (which lives inside SampleClass) requires new instance of SampleService class to work properly.

How to inject SampleService class new instance on every invocation of DoOpertation() without using 'new' keyword?

Modification as per Athanasios Kataras's suggestion

Introduced new factory class

        public class LoggerFactory : ILoggerFactory
        {
            public IEventLog CreateLogger(string type)
            {
                if (type == "Event")
                    return new EventLog();
                else
                    return null;
            }
        }

        public interface ILoggerFactory
        {
            IEventLog CreateLogger(string type);
        }

On the class which instantiate only once,

 public class SampleClass //instantiated only once
   {
    public void DoOpertation()//will be called by every incoming request
    {
      var eventLogBuilder = _factory.CreateLogger("Event");
     //var dependentService = new SampleService(); //replace with above simple factory class call
     //do operation on dependentService instance
     ....
   }
  }

CodePudding user response:

I would go with a simple factory solution.

  1. Create the IServiceFactory interface with the CreateService(options) function
  2. Create a class implementing it with the responsibility of returning the proper service insurance.
  3. Inject the factory implementation

In your function call the factory interface. This will also enable you to change the creation strategy in the future if you need it.

The solution going with the built in provider, looks like a service locator anti pattern to me, so I would advise against it.

CodePudding user response:

Register Sampleclass as a singleton and SampleService as a transient. Then inject IServiceProvider into SampleClass. Use the ServiceProvider to then create the SampleServer.

services.AddSingleton<SampleClass>();
services.AddTransient<SampleService>();

...

public class SampleClass //instantiated only once
{
    private readonly IServiceProvider _provider;
    
    public SampleClass(IServiceProvider provider)
    {
        _provider = provider;
    }
    
    public void DoOpertation()//will be called by every incoming request
    {
    var dependentService = _provider.GetService<SampleService>();
    //do operation on dependentService instance
    ....
    }
}

  •  Tags:  
  • Related