Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use a Dependency Injection container?

I have completed the 'InTheBox' WPF Training by Karl Shiffet and have found it be an excellent resource for learning WPF. One thing it did bring up was the use of Dependency Injection and the Unity Container. Here is the section of code that raised some questions for me:

public partial class App : Application {

    protected override void OnStartup(StartupEventArgs e) {

        IUnityContainer container = new UnityContainer();

        container.RegisterType<IDialogService, ModalDialogService>(
            new ContainerControlledLifetimeManager());

        container.RegisterType<IEventRepository, EventRepository>(
            new ContainerControlledLifetimeManager());

        MainWindow window = container.Resolve<MainWindow>();

        window.DataContext = container.Resolve<MainWindowViewModel>();

        window.Show();
    }
}

The dependencies are being registered into the UnityContainer and then injected by the UnityContainer into the MainWindowViewModel. My question is why use the container? Why not just use the following piece of code that achieves the same thing as far as dependency injection is concerned:

protected override void OnStartup(StartupEventArgs e)
{
    IDialogService dialogService = new ModalDialogService();
    IEventRepository eventRepository = new EventRepository();

    MainWindow window = new MainWindow();
    window.DataContext = 
        new MainWindowViewModel(eventRepository, dialogService);
    window.Show();
}

I am still injecting the dependencies into the constructor from the composition root so I see no benefit in this case to using the UnityContainer.

I appreciate it obviously exists for a reason but could someone explain whether in this situation it adds anything? Also, is there another situation where the use of container like this is truly a no-brainer?

like image 363
andrew_scfc Avatar asked Mar 24 '23 16:03

andrew_scfc


1 Answers

Using a DI container in a simple case like this doesn't really do much for you. It starts to make more sense when things get more complex and it also minimizes the effect of dependency changes.

Say for example, you have an ILoggingService that all of your dependencies now use. When using a DI container like Unity you only have to add one line of code.

    protected override void OnStartup(StartupEventArgs e)
    {
        IUnityContainer container = new UnityContainer();
        container.RegisterType<IDialogService, ModalDialogService>();
        container.RegisterType<IEventRepository, EventRepository>();
        container.RegisterType<ILoggingService, LoggingService>(); // added

        MainWindow window = container.Resolve<MainWindow>();
        window.DataContext = container.Resolve<MainWindowViewModel>();
        window.Show();
    }

When doing it yourself, you have to add one line of code, and modify 3 lines of code.

    protected override void OnStartup(StartupEventArgs e)
    {
        ILoggingService loggingService = new LoggingService(); // added
        IDialogService dialogService = new ModalDialogService(loggingService); // modified
        IEventRepository eventRepository = new EventRepository(loggingService); // modified

        MainWindow window = new MainWindow();
        window.DataContext = new MainWindowViewModel(eventRepository, dialogService, loggingService); // modified
        window.Show();
    }

When using more advanced containers that can scan for types to register, its possible that you wouldn't have to change any code in your composition root. Here is an example using AutoFac.

    protected override void OnStartup(StartupEventArgs e)
    {
        var builder = new ContainerBuilder();
        var assembly = Assembly.GetExecutingAssembly();
        builder.RegisterAssemblyTypes(assembly)
               .AsSelf()
               .AsImplementedInterfaces();
        var container = builder.Build();

        MainWindow window = container.Resolve<MainWindow>();
        window.DataContext = container.Resolve<MainWindowViewModel>();
        window.Show();
    }
like image 79
Tim B Avatar answered Apr 03 '23 06:04

Tim B