Ioc Container provides some benefits when using Dependency Injection design pattern.
Let’s see sample code:
Interface and Class
public interface ISender
{
void Send(string message);
}
public class EmailSender : ISender
{
public void Send(string message)
{
Console.WriteLine("{0} has been sent via email.", message);
}
}
public class CourierSender : ISender
{
public void Send(string message)
{
Console.WriteLine("{0} has been sent via a courier.", message);
}
}
Case 1: DI without Ioc Container
public class Messenger
{
private ISender _sender;
public Messenger(ISender sender)
{
_sender = sender;
}
public void Send(string message)
{
_sender.Send(message);
}
}
class Program
{
static void Main(string[] args)
{
// Send via email
var messenger = new Messenger(new EmailSender());
messenger.Send("Congrats!");
// Send via courier
messenger = new Messenger(new CourierSender());
messenger.Send("Congrats!");
}
}
This has the following problems:
- The more Messenger class is used, the more new intantiation. This will cause less maintenancebility.
- EmailSender and CourierSender depend on other classes. This makes instantiating them to each layer when they have hierarchy.
- Less maintenancebility to changes to EmailSender and CourierSender structures.
IoC Container provides solutions for these problems.
Following is a sample usage of IoC container, Ninject. Ninject is avaliable on Nuget package manager.
Case 2: DI with Ioc Container
using Ninject;
class Program
{
static void Main(string[] args)
{
// IoC Container
var kernel = new StandardKernel();
// Send via email
kernel.Bind<ISender>().To<EmailSender>();
kernel.Get<ISender>().Send("Congrats!");
// Send via courier
kernel.Rebind<ISender>().To<CourierSender>();
kernel.Get<ISender>().Send("Congrats!");
}
}
As shown in the sample code, IoC Conatiner provides some benefits:
- Centralizing instantiation
- Encapsulating class members
- More testability with using mock code
These provide maintenancebility, flexibility and testability.