尝试使用MVVM模式将WPF应用程序回填以使用依赖注入。我对DI并不太熟悉,之前只使用过一次,但我认为我理解了其中涉及的原则。
我需要确保所有绑定都在一个地方注册——应用程序根节点。在WPF中,这是OnStartup方法。因此,我使用Ninject并将其放入我的应用程序中,尝试自动绑定我的存储库类到初始视图:
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();
}
从现在开始,我将使用数据模板资源来设置上下文:
<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加载到窗口中:
NavigationHelper.NewWindow(this, new QuoteViewModel(quote, new Repository()));
这行代码正是我第一次接触 DI 的原因 - 我无法测试它,因为我无法 mock 出这个依赖项。在这种情况下添加 DI 对我没有帮助,因为我只能在 OnStartUp 中使用我的 IoC 容器,所以我不能使用 kernel.Get 来获取我的 QuoteViewModel,对吗?
在 SO 上搜寻后,我发现有很多人推荐我使用服务定位器来解决这个问题。这对我来说很新颖,但也有很多人告诉我,将其用于 DI 是一种反模式,应该避免使用。到底谁是对的呢?
或许更重要的是,有没有什么巧妙的方法来解决这个问题?我看到了一些其他的例子,需要使用大量不同的包才能使它工作。现在,MVVM 和 DI 似乎就是不能完美地协作。