Tilak Dewangan
Tilak Dewangan

Reputation: 361

Get dependency when needed?

Is there any way to get/fetch dependencies only when it is needed?

public class DependentClass
{
    public DependentClass(IMandatoryDependency mandatoryDependency, IDependency1 dependency1, IDependency2 dependency2, IDependency3 dependency3)
    {
        // Assigned to class level property
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency1.CallDependecy1Method();
    }

    public void MethodsTwo()
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency2.CallDependecy2Method();
    }

    public void MethodsThree()
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency3.CallDependecy3Method();
    }
}

From the above snippet, I would like to get the dependency for individual methods when I am inside the methods itself. Something like this:

public class DependentClass
{
    public DependentClass(IMandatoryDependency mandatoryDependency)
    {
        // Assigned to class level property
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        DIContainer.GetDependency<IDependency1>().CallDependecy1Method();
    }

    public void MethodsTwo()
    {
        mandatoryDependency.CallMandatoryMethod();
        DIContainer.GetDependency<IDependency2>().CallDependecy2Method();
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        DIContainer.GetDependency<IDependency3>().CallDependecy3Method();
    }
}

Upvotes: 0

Views: 1102

Answers (3)

Voodoo
Voodoo

Reputation: 1658

You need to register services as Lazily in StartUp.cs.

services.AddTransient<IDependecy1, Dependecy1>();
services.AddTransient(serviceProvider => new Lazy<IDependecy1>(() => serviceProvider.GetRequiredService<IDependecy1>()));

Then in your Controller use dependency as Lazy

public class DependentClass
{
    private readonly Lazy<IDependency1> _dependency1;
    public DependentClass(IMandatoryDependency mandatoryDependency, Lazy<IDependency1> dependency1)
    {
        // Assigned to class level property
        _dependency1 = dependency1;
    }

    public void MethodsOne()
    {
        mandatoryDependency.CallMandatoryMethod();
        _dependency1.Value.CallDependecy1Method();
    }
}

If you are using IDependency1 just in one method, so you can resolve the dependency using FromServices in .NET core instead of injecting dependency in constructor.

public void MethodsOne([FromServices] IDependency1 dependency1)
    {
        mandatoryDependency.CallMandatoryMethod();
        dependency1.CallDependecy1Method();
    }

Upvotes: 1

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

in asp.net core we can inject IServiceProvider in controller and resolve dependencies ourselves on run-time like:

private IServiceProvider _serviceProvider;
private IMandatoryDependency _mandatoryDependency;
public DependentClass(IMandatoryDependency mandatoryDependency,
                      IServiceProvider serviceProvider)
{
    _serviceProvider = serviceProvider;
    _mandatoryDependency = mandatoryDependency;
}

and in method we can request the provider to give the instance of a particular dependency like :

public void MethodsOne()
{
    mandatoryDependency.CallMandatoryMethod();
    _serviceProvider.GetService(typeof(IDependency1)).CallDependecy1Method();
}

But it is not considered a good idea to inject IServiceProvider see :

Why not inject IServiceProvider instead of each individual dependency?

You can look in more details about the dependency injection service particularly in asp.net core at following :

https://andrewlock.net/new-in-asp-net-core-3-service-provider-validation/

http://www.binaryintellect.net/articles/17ee0ba2-99bb-47f0-ab18-f4fc32f476f8.aspx

Also read about best practices for Dependency Injection in asp.net core:

https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96

Upvotes: 1

Mostafa Mohamed Ahmed
Mostafa Mohamed Ahmed

Reputation: 649

Assuming that you are using an IOC container ,You can inject an instance of the container it self in the constructor and then used this instance to resolve your services bad it's not a good practice , you might be looking for something like this

Another good option would be making the optional dependencies a Lazy objects , by simply using the Lazy class , so you code will be Lazy<IDependency1>

using the lazy pattern ensure that the objects are not instantiated unless you actually want to access them , you can read more about it here

Upvotes: 3

Related Questions