向MVVM应用程序添加依赖注入 [英] Adding Dependency Injection to an MVVM application

查看:286
本文介绍了向MVVM应用程序添加依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用MVVM模式回填WPF应用程序以与依赖项注入一起使用.我对DI并不太熟悉,以前只使用过它一次,但是我想我了解其中涉及的原理.

Trying to backfill a WPF application using the MVVM pattern to work with dependency injection. I'm not overly familiar with DI, having worked with it only once before, but I think I understand the principles involved.

我需要确保所有绑定都在一个位置注册-应用程序根目录.在WPF中,这是OnStartup方法.因此,我抓住了Ninject并将其扔到我的应用程序中,尝试将存储库类自动绑定到初始视图:

I need to ensure that the bindings are all registered in one place - the application root. In WPF, this is the OnStartup method. So, I grabbed Ninject and threw it into my application to try and automatically bind my repository class to the initial view:

private void OnStartup(object sender, StartupEventArgs e)
{
    IKernel kernel = new StandardKernel();
    kernel.Bind<IRepository>().To<Repository>();

    Views.MainView view = new Views.MainView();
    view.DataContext = kernel.Get<ViewModels.MainViewModel>();

    view.Show();
}

从现在开始,我将使用数据模板资源来设置上下文:

From hereon in, I set contexts by using a data template resource:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:views="clr-namespace:My.Views"
                    xmlns:models="clr-namespace:My.ViewModels" >
    <DataTemplate DataType="{x:Type models:MyViewModel}" >
        <views:MyView />
    </DataTemplate>
    <!-- etc -->
</ResourceDictionary>

它有效.伟大的!但是,在MainViewModel中,我按下一个按钮,然后将其他类型的ViewModel加载到窗口中:

And it works. Great! However, in MainViewModel I press a button and load a different type of ViewModel into the window:

NavigationHelper.NewWindow(this, new QuoteViewModel(quote, new Repository()));

这行代码恰恰是使我首先购买DI的原因-我无法对其进行测试,因为我无法在此处模拟出依赖关系.在这种情况下添加DI完全没有帮助,因为我只能在OnStartUp中使用IoC容器,所以我不能使用kernel.Get来获取QuoteViewModel,对吗?

This line of code is exactly what bought me to DI in the first place - I can't test this, because I can't mock out the dependency here. Adding DI in this instance isn't helping me at all because I'm only supposed to use my IoC container in OnStartUp, so I can't use kernel.Get to fetch my QuoteViewModel, right?

窥探SO,我看到许多人建议我使用服务定位器解决此问题.这对我来说是新的,我也看到很多人告诉我,将其用于DI是一种反模式,不应被粗暴的人所碰触.谁是对的?

Snooping around SO I see a number of people recommending I solve this using a service locator. This is new to me, and I also see a number of people telling me that using this for DI is an anti-pattern which shouldn't be touched with a bargepole. Who's right?

也许更重要的是,对于这个问题是否有一个整洁的解决方案?我看过其他一些示例,这些示例要求使用各种不同的软件包才能使其正常工作.现在,感觉MVVM和DI并不能很好地发挥作用.

And perhaps more importantly, is there a neat solution to this issue? I've seen a couple of other examples that demand a smorgasbord of different packages to make it work. Right now, it feels like MVVM and DI just aren't made to play nice with each other.

推荐答案

您快到了.您缺少两件事:

You're almost there. You're missing two things:

您需要一个能够为您创建子VM的工厂.为该工厂引入一个接口,以便您可以在测试中替换它.

You need a factory that is able to create the child VM for you. Introduce an interface for this factory, so you can replace it in tests.

public interface IVmFactory {
    IQuoteViewModel CreateQuoteViewModel();
}

您可以自己实现此接口,也可以让NInject为您完成.

请务必在DI容器中注册该工厂,以便该容器能够在收到实例化以工厂为依赖项的类的请求时对其进行解析.

Be sure to register this factory in the DI container, so that the container is able to resolve it when it receives requests to instantiate classes that have the factory as dependency.

现在,您可以使用标准构造函数注入将IVmFactory注入视图模型:

Now, you can inject the IVmFactory into the view model with standard constructor injection:

public class MainViewModel {
    public MainViewModel(IVmFactory vmFactory) {
        _vmFactory = vmFactory;
    }

    // ...
}

DI和MVVM

一旦找到解决WPF的默认构造函数问题的方法(当您尝试让WPF实例化VM时),DI和MVVM就可以很好地协同工作.

DI and MVVM

DI and MVVM work together very well once you find your way around the default constructor problem of WPF (when you try to let WPF instantiate VMs).

DI显然不是反模式,但服务定位器是.不幸的是,通常建议将服务定位器与MVVM一起使用,因为它使您可以快速入门,而不必创建工厂并正确注入它们.需要权衡的是要快速开始,而不是干净整洁.可测试的设计-自行决定.

DI is clearly not an anti-pattern, but service locator is. Unfortunately, service locator is often recommended together with MVVM, because it enables you to get started quickly without having to create factories and properly inject them. The trade-off is to get started quickly vs. having a clean & testable design - decide for yourself.

这篇关于向MVVM应用程序添加依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆