wpf - 为什么要使用依赖注入(inject)容器?

标签 wpf design-patterns dependency-injection composition

我已经完成了'InTheBox' WPF Training Karl Shiffet 发现它是学习 WPF 的绝佳资源。它确实带来的一件事是使用依赖注入(inject)和 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();
    }
}

依赖项被注册到 UnityContainer 中,然后由 UnityContainer 注入(inject)到 MainWindowViewModel 中。我的问题是为什么要使用容器?就依赖注入(inject)而言,为什么不直接使用以下实现相同目的的代码:

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();
}

我仍在将依赖项从组合根注入(inject)到构造函数中,因此在这种情况下我认为使用 UnityContainer 没有任何好处。

我很欣赏它的存在显然是有原因的,但是有人可以解释在这种情况下它是否会增加任何东西吗?另外,是否还有另一种情况,使用这样的容器真的很容易?

最佳答案

在像这样的简单情况下使用 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();
    }

自己做的时候,要加一行代码,修改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();
    }

当使用可以扫描类型以注册的更高级的容器时,您可能不必更改组合根中的任何代码。这是使用 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();
    }

关于wpf - 为什么要使用依赖注入(inject)容器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16958013/

相关文章:

wpf - WPF 类库中的全局静态资源?

wpf - 如何在listview的datatemplate中订阅事件

wpf - 将两个 WPF 动画链接在一起

javascript - 将相同的代码添加到多个函数

c# - Autofac 通用工厂

dependency-injection - 如果存在另一个相同类型的 CDI bean,则否决 CDI bean

wpf - TabControl - 使 TabItem 出现在内容顶部

java - 数据传输对象类可以包含其他对象吗?

javascript - 用原型(prototype)继承覆盖方法

spring - 如何在 Spring 应用程序的 servlet 过滤器中 Autowiring bean?