如何在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
- 依次,每个
都有一个ItemsControlTier2UserControl
绑定到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>
}