I have a console .NET core application which uses the Microsoft.Extensions.DependencyInjection
library as a dependency injection framework.
I want to use this framework to inject a dependency two "levels down" without having to redundantly mention this dependency in the middle layer. How do I do this?
Currently, the only way I can inject a dependency is to pass it down the levels until it is needed. Here is my standalone console application that demonstrates the requirement. Its a simple program that calculates a persons net worth based on example asset and liability amounts. (It literally just subtracts the two amounts).
The Program.cs
file contains the program Main entry point and registers the dependencies.
Program.cs:
public class Program
{
private static IServiceProvider _serviceProvider;
public static void Main(string[] args)
{
RegisterServices();
IServiceScope scope = _serviceProvider.CreateScope();
scope.ServiceProvider.GetRequiredService<ConsoleApplication>().Run();
DisposeServices();
}
private static void RegisterServices()
{
var services = new ServiceCollection();
services.AddSingleton<ICalculator, Calculator>();
services.AddSingleton<ConsoleApplication>();
_serviceProvider = services.BuildServiceProvider(true);
}
private static void DisposeServices()
{
if (_serviceProvider == null)
{
return;
}
if (_serviceProvider is IDisposable)
{
((IDisposable)_serviceProvider).Dispose();
}
}
}
After setting up the dependency injections, Program.cs
runs the ConsoleApplication.cs
Run
method.
ConsoleApplication.cs:
internal class ConsoleApplication
{
private readonly ICalculator _calculator;
public ConsoleApplication(ICalculator calculator)
{
_calculator = calculator;
}
public void Run()
{
Person person = new Person(_calculator)
{
Assets = 1000m,
Liabilities = 300m
};
Console.WriteLine(person.GetNetWorth());
}
}
The above code instantiates an example Person
and invokes the GetNetWorth
method. The Person class is shown below.
Person.cs:
public class Person
{
private readonly ICalculator _calculator;
public Person(ICalculator calculator)
{
_calculator = calculator;
}
public decimal Assets {get; set;}
public decimal Liabilities {get; set;}
public decimal GetNetWorth()
{
decimal netWorth = _calculator.Subtract(Assets, Liabilities);
return netWorth;
}
}
The Person
class has a dependency on Calculator
as shown below:
Calculator.cs:
public interface ICalculator
{
decimal Add(decimal num1, decimal num2);
decimal Subtract(decimal num1, decimal num2);
decimal Multiply(decimal num1, decimal num2);
decimal Divide(decimal num1, decimal num2);
}
public class Calculator : ICalculator
{
public decimal Add(decimal num1, decimal num2) => num1 + num2;
public decimal Subtract(decimal num1, decimal num2) => num1 - num2;
public decimal Multiply(decimal num1, decimal num2) => num1 * num2;
public decimal Divide(decimal num1, decimal num2) => num1 / num2;
}
Given the program above, you can see the problem here is that the class ConsoleApplication.cs
has this line of code:
private readonly ICalculator _calculator;
public ConsoleApplication(ICalculator calculator)
{
_calculator = calculator;
}
That code is redundant and should be avoided because ConsoleApplication.cs
doesn't have this dependency and therefore shouldn't know anything about it. The only reason I'm forced to include it is to pass it the next level down to Person
which does need the dependency.
With the example above, how to I adjust the program.cs
to avoid passing down the dependency? I have a feeling that I'm using the Microsoft.Extensions.DependencyInjection
framework completely wrong. The whole point of using DI containers is to circumvent this problem. I might aswell have not used a DI Container at all and the code would have been simpler.
I have read numerous SO posts asking similar questions. However, they don't cater for my specific case of a console application, .NET and using the Microsoft.Extensions.DependencyInjection;
DI Framework.