Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中使用Ninject创建ViewModel的多个实例,同时避免代码气味?_C#_Wpf_Dependency Injection - Fatal编程技术网

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

如何在C#中使用Ninject创建ViewModel的多个实例,同时避免代码气味?,c#,wpf,dependency-injection,C#,Wpf,Dependency Injection,我的问题有两个部分 第一个问题是,如何使用依赖项注入创建ViewModel类的多个实例?榜样 我正在创建一个WPF应用程序,使用MVVM模式,使用Ninject创建一个SQLite数据库,使用EntityFramework.Core。它的结构是这样的 我有一个视图,比如Tier1View,它绑定到一个ViewModel, Tier1ViewModel 在tier1视图中是一个带有 Tier2UserControl的DataTemplate,用于ItemsControl的ItemSource 是

我的问题有两个部分

第一个问题是,如何使用依赖项注入创建
ViewModel
类的多个实例?榜样

我正在创建一个
WPF
应用程序,使用
MVVM
模式,使用
Ninject
创建一个
SQLite
数据库,使用
EntityFramework.Core
。它的结构是这样的

  • 我有一个
    视图
    ,比如
    Tier1View
    ,它绑定到一个
    ViewModel
    Tier1ViewModel
  • tier1视图中
    是一个带有
    Tier2UserControl
    DataTemplate
    ,用于
    ItemsControl的
    ItemSource
    是一个
    可观察的集合
    有效地
    绑定
    数据上下文
    对于每个
    Tier2UserControl
    Tier2ViewModel
  • 依次,每个
    Tier2UserControl
    都有一个ItemsControl
    Tier3UserControl
    绑定到
    observeCollection

由于TIR2和TiR3视图模型的集合在编译时的大小不确定,因为它们依赖于数据库中的表来获取初始数据,并且可以在运行时发生改变,这就排除了使用构造函数注入的方式这样粗糙的可能性(这一点我甚至感到惭愧)。 如何在同一个类中创建依赖项的多个实例?以前有人建议我在一个问题上使用工厂(Ninject支持),这个问题是关于将变量传递给注入依赖项的,我已经创建了一个成功的实现

Collection.Add(IViewModelFactory.CreateTierNViewModel());
并将工厂注入到上述层的构造函数中

public class Tier2ViewModel
{
   public Tier2ViewModel(Tier2Entity tier2Entity) { //... }
}
然而,这引出了我问题的第二部分

每个实例都需要在集合中可识别-因此运行时数据必须传递给“已创建”的每个实例

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

Tier3ViewModels
将通过包含
SQLite
数据库中唯一的
实体
来区分(它们实际上是那些
实体
视图模型
),因为
实体
只能在
运行时知道,正确的方法是创建依赖项的实例(因为缺乏关于其他方法的知识,使用工厂),然后在
ViewModel
中有一个将我的实体作为参数的方法(或者更好的方法是该实体的抽象,例如
IEntityType


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

如果必须在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>
   }
}

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

这类回答我的问题,因为工厂是最有意义和最有效的!但这不是在类中创建了与工厂的耦合吗?这就是我们试图用DI消除的?不,不是。
Tier1ViewModel
仅取决于接口
ITier2ViewModelFactory
,而不是工厂实现本身。因此,您可以在需要单元测试时模拟factory界面
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>
   }
}
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>
   }