Reputation: 1287
Below is a very basic console App example that I put on understanding Dependency Injection & IOC. I somehow could not see the value as in this case I still need to modify my program.cs to inject the new implementation of Interface. Also, how unit testing fits into this?
Program.cs
using Microsoft.Extensions.DependencyInjection;
namespace UnderstandingDI
{
class Program
{
static void Main(string[] args)
{
var serPro = new ServiceCollection()
.AddSingleton<IMessage, Messaging>()
.BuildServiceProvider();
var bar = serPro.GetService<IMessage>();
bar.PrintMessage("Hello World!----");
}
}
}
IMessage.cs
namespace UnderstandingDI
{
public interface IMessage
{
public void PrintMessage(string Msg);
}
}
Messaging.cs
using System;
namespace UnderstandingDI
{
public class Messaging : IMessage
{
public void PrintMessage(string Msg)
{
Console.WriteLine(Msg + "From Messaging");
}
}
}
NewMessaging.cs
using System;
namespace UnderstandingDI
{
class NewMessaging : IMessage
{
public void PrintMessage(string Msg)
{
if (Msg.StartsWith("Hello"))
{
Console.WriteLine("Msg starting with Hello");
}
else
{
Console.WriteLine(Msg);
}
}
}
}
Here, if I have to swap Messaging.cs
implementation with NewMessaging.cs
which both implement IMessage
interface, I still need to modify my Program.cs
to inject this NewMessaging.cs
like this:
var serPro = new ServiceCollection()
.AddSingleton<IMessage, NewMessaging>()
.BuildServiceProvider();
If so, why MS claims that DI addresses one prob of To replace MyDependency with a different implementation, the class must be modified
src:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1
What am I missing?
Upvotes: 1
Views: 367
Reputation: 15227
In your example, there is no dependency injection.
Dependency injection literally means: you inject a dependency into a class, you don't construct it yourself and don't actively ask some other component for that dependency.
There is no class in your example that actually has a dependency (except of the Program
of course).
The Main
method in your Program.cs
is a composition root. This is where you wire-up the DI container ("service provider"). Of course, you will need to modify it when you want to change the implementations.
Now, imagine you have a class that does have a dependency IMessage
:
class ChatBot
{
private readonly IMessage message;
public ChatBot(IMessage message) => _message = message;
public void Greet() => _message.PrintMessage("Hello World!");
}
If you replace the IMessage
implementation in the composition root, the ChatBot
class won't even know it. You don't have to touch that class.
Imagine you have 50 classes that all use IMessage
to print messages. Changing the implementation still causes the change in the composition root, but only there. The other 50 classes don't need to be changed.
This also helps you in unit testing. If you want to test the ChatBot
class, you can mock the IMessage
dependency in a way you need it. You also have a direct knowledge, that the ChatBot
class needs an IMessage
and nothing besides that. Your code is testable then (no hidden calls to unknown singletons, static classes etc.)
Hope my explanation helps. Consider reading a great book "Dependency Injection in .NET" where you'll find a lot of good ideas about designing maintainable software in .NET.
Upvotes: 1