为什么使用依赖注入容器?

and*_*cfc 4 wpf design-patterns dependency-injection composition

我已经完成了Karl Shiffet 的'InTheBox'WPF培训,并发现它是学习WPF的绝佳资源.它确实提出的一件事是使用依赖注入和Unity容器.以下是为我提出一些问题的代码部分:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

依赖项正在注册到UnityContainer中,然后由UnityContainer注入到MainWindowViewModel中.我的问题是为什么要使用容器?为什么不使用下面的代码来实现与依赖注入相同的事情:

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();
}
Run Code Online (Sandbox Code Playgroud)

我仍然从组合根注入构造函数中的依赖项,所以我认为在这种情况下使用UnityContainer没有任何好处.

我很欣赏它显然存在是有原因但有人可以解释在这种情况下它是否添加了什么?另外,还有另一种情况,使用像这样的容器真的是一个明智的选择吗?

Tim*_*m B 5

在像这样的简单情况下使用DI容器对你来说并没有多大帮助.当事情变得更复杂时它开始变得更有意义,并且它也最小化依赖变化的影响.

比如说,您有一个ILoggingService,您的所有依赖项现在都使用.使用像Unity这样的DI容器时,您只需要添加一行代码.

    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();
    }
Run Code Online (Sandbox Code Playgroud)

在自己动手时,您必须添加一行代码,并修改3行代码.

    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();
    }
Run Code Online (Sandbox Code Playgroud)

使用可以扫描要注册的类型的更高级容器时,可能不必更改组合根目录中的任何代码.以下是使用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();
    }
Run Code Online (Sandbox Code Playgroud)