如何使用 Ninject 在 C# 中创建 ViewModel 的多个实例,同时避免代码异味?



我的问题有两个部分。

首先是,如何使用依赖注入创建ViewModel类的多个实例?例;

我正在使用MVVM模式创建一个WPF应用程序,Dependency InjectionNinjectSQLiteDatabaseEntityFramework.Core。它的结构是这样的;

  • 我有一个View,比如说Tier1View绑定到一个ViewModelTier1ViewModel.
  • Tier1View内是一个ItemsControl,带有Tier2UserControlDataTemplateItemsControlItemSource是一种有效BindingObservableCollection<Tier2ViewModel>Data Context每个Tier2UserControl到一个实例Tier2ViewModel.
  • 反过来,每个Tier2UserControl都有一个 项目控件Tier3UserControl绑定ObservableCollection<Tier3ViewModel>.

由于 Tier2 和 Tier3 ViewModel 的集合在编译时的大小不确定,因为它们依赖于数据库中的表作为初始数据,并且可以在运行时更改,这消除了以像此示例这样粗糙的方式使用构造函数注入的可能性(以至于我甚至羞于考虑它(。

public Tier1ViewModel(ITier2ViewModel firstInstance, ITier2ViewModel secondInstance, ...)
{
Collection.add(firstInstance);
Collection.add(secondInstance);
...
}

如何在同一类中创建依赖项的多个实例?之前有人建议我使用工厂(由 Ninject 支持(来解决我提出的关于将变量传递给注入依赖项的问题,并且我已经创建了成功的实现。

Collection.Add(IViewModelFactory.CreateTierNViewModel());

并将工厂注入到上层的构造函数中。

然而,这导致了我问题的第二部分。

每个实例都需要在集合中可识别 - 因此Run-Time Data必须传递给每个实例"已创建"。

根据本文,使用工厂会增加应用程序的复杂性和可维护性。在我更好地理解编程的目标中,我试图避免的事情。它还指出,运行时数据不应注入到对象的构造中,而应通过方法传入。

通过包含来自SQLite数据库的唯一Entities来区分Tier3ViewModels(它们实际上是这些EntitiesView Models(,因为Entities只能在run-time时知道,是创建依赖项实例的正确方法(由于缺乏对其他方式的了解, 使用工厂(,然后在该ViewModel中有一个方法,将我的实体作为参数(或者更好的是该实体的抽象,例如IEntityType(?

var instanceOf = Factory.CreateViewModel();
instanceOf.AddingMethod(IEntity);

我希望其中一些是可以翻译的!提前感谢任何帮助!

如果必须在 ViewModel 上传递数据对象,则在构造函数中声明这些对象。

public class Tier2ViewModel
{
public Tier2ViewModel(Tier2Entity tier2Entity) { //... }
}

从那里,您可以在不使用依赖项注入的情况下创建Tier2ViewModel,只需在Tier1ViewModel类中手动创建它们。

public class Tier1ViewModel
{
private void LoadTier2()
{
//TODO: load tier2Entities using EF
//TODO: foreach tier2Entity, create new Tier2ViewModel
//TODO: add each Tier2ViewModel instance to ObservableCollection<Tier2ViewModel>
}
}

但是,如果您真的想使用依赖注入,那么您就走上了使用Factory类的正确轨道。而是在CreateViewModel方法上传递Entity对象。

public interface ITier2ViewModelFactory
{
Tier2ViewModel CreateViewModel(Tier2Entity tier2Entity);
}
public class Tier2ViewModelFactory : ITier2ViewModelFactory
{
public Tier2ViewModel CreateViewModel(Tier2Entity tier2Entity)
{
return new Tier2ViewModel(tier2Entity);
}
}
public class Tier1ViewModel
{
private readonly ITier2ViewModelFactory _tier2ViewModelFactory;
private void LoadTier2()
{
//TODO: load tier2Entities using EF
//TODO: foreach tier2Entity, call _tier2ViewModelFactory.CreateViewModel(tier2Entity)
//TODO: add each Tier2ViewModel instance to ObservableCollection<Tier2ViewModel>
}

如您所见,工厂添加了另一层抽象,对我来说,这对于使用 DI 创建实例是不必要的。就个人而言,我只会在对象的实例化涉及需要测试的复杂逻辑时才使用Factory模式。

最新更新