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

时间:2018-06-08 23:59:37

标签: c# wpf dependency-injection

我的问题分为两部分。

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

我正在使用WPF模式创建MVVM应用,使用Dependency Injection创建Ninject,使用{{1}创建SQLite Database }。它的结构如此;

  • 我有EntityFramework.Core,说View绑定到Tier1ViewViewModel
  • Tier1ViewModel内的Tier1View是{。}} ItemsControl的{​​{1}},DataTemplate的{​​{1}} 有效Tier2UserControlItemSource 每个ItemsControl到{1}}的实例。ObservableCollection<Tier2ViewModel> Binding
  • 反过来,每个Data Context都有一个ItemsControl Tier2UserControl绑定到Tier2ViewModel

由于Tier2和Tier3 ViewModel的集合在编译时具有不确定的大小,因为它们依赖于数据库中的表来获取初始数据并且可以在运行时更改,这消除了使用Constructor注入的可能性粗糙的一种方式就像这个例子(我甚至羞于考虑它)。

Tier2UserControl

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

Tier3UserControl

并将工厂注入上面的Tier构造函数。

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

每个实例都需要在集合中可识别 - 因此ObservableCollection<Tier3ViewModel>必须传递给每个实例&#34;创建&#34;。

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

public Tier1ViewModel(ITier2ViewModel firstInstance, ITier2ViewModel secondInstance, ...) { Collection.add(firstInstance); Collection.add(secondInstance); ... } 可以通过在Collection.Add(IViewModelFactory.CreateTierNViewModel()); 数据库中包含唯一Run-Time Data来区分Tier3ViewModels,它们实际上是那些Entities的{​​{1}},因为SQLite只能在View Models知道,所以是创建依赖关系实例的正确方法(因为缺乏关于其他方式的知识,使用工厂),然后在其中有一个方法{ {1}}将我的实体作为参数(或者更好的是该实体的抽象,例如Entities)?

Entities

我希望其中一些可以翻译!在此先感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

如果必须在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类了。而是在Entity方法上传递CreateViewModel对象。

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模式。