在表示逻辑层(PLL)中,我有所谓的“视图模型”类,它们实现/扩展业务逻辑层(BLL)中定义的接口,如下所示:
namespace BLL.Abstract.POCO
{
// also implemented in data access layer (DAL) by data model entities
public interface ISomeDomainModelEntity
{
string Name { get; set; }
string Description { get; set; }
}
}
namespace PLL.Abstract.ViewModels
{
public interface ISomeDomainModelEntityViewModel
: ISomeDomainModelEntity, INotifyPropertyChanged
{
bool IsSelected { get; set; }
}
}
namespace PLL.Concrete.ViewModels
{
public class SomeDomainModelEntityViewModel
: ViewModelBase, ISomeDomainModelEntityViewModel
{
private string _name;
private string _description;
private bool _isSelected;
public string Name { get { return _name; } set { _name = value; NotifyPropertyChanged(() => Name); } }
public string Description { get { return _description; } set { _description = value; NotifyPropertyChanged(() => Description); } }
public bool IsSelected { get { return _isSelected; } set { _isSelected = value; NotifyPropertyChanged(() => IsSelected); } }
}
}
请注意,ViewModelBase
是一个抽象类,允许这种强烈的强类型INotifyPropertyChanged
实现。
上述实现的IsSelected
属性显然只在表示层中显示(可视化列表中显示的几个这些对象,其中ItemTemplate
具有绑定其ListBox
的{{1}} IsChecked
属性IsSelected
),表示逻辑在返回业务逻辑层之前知道如何使用它。
我遇到的问题是,我发现名称“ViewModel”与此冲突:
namespace PLL.Abstract.ViewModels // hmmm...
{
public interface ISomeWindowViewModel
{
ObservableCollection<ISomeDomainModelEntityViewModel> SomeItems { get; }
}
}
ISomeWindowViewModel
的实施最终分配给视图的DataContext
属性:
namespace PLL.Concrete.ViewModels
{
public class SomeWindowViewModel : WindowViewModelBase, ISomeWindowViewModel
{
private readonly ObservableCollection<ISomeDomainModelEntityViewModel> _items;
public SomeWindowViewModel(IView view, ObservableCollection<ISomeDomainModelEntityViewModel> items)
: base(view)
{
_items = items;
}
public ObservableCollection<ISomeDomainModelEntityViewModel> SomeItems { get { return _items; } set { _items = value; } }
}
}
namespace PLL.Abstract
{
public abstract class WindowViewModelBase : ViewModelBase
{
public IView View { get; private set; }
protected WindowViewModelBase(IView view)
{
View = view;
View.DataContext = this;
}
}
}
这是我在阅读了Mark Seeman的 .NET中的依赖注入中如何将DI应用于WPF之后开始的重大重构的结果(迄今为止的优秀阅读,尚未完成)虽然起初将View实现注入到ViewModel中似乎有些倒退,但我可以理解通过处理视图的显示和关闭获得的控制/简单性。在重构之前,我有一个带有BLL的工作应用程序,它与DAL和PLL紧密耦合;现在BLL没有任何依赖关系,而且非常棒。
我仍然在重新配置组合根目录(使用Ninject.Extension.Conventions),所以在一天结束时我可能会意识到我需要进行一些调整才能使其全部工作。 ..它可能会受伤,但我已经准备好了!
所以问题如下:
答案 0 :(得分:1)
在我看来,太多了。架构应该是灵活的,当你闻到什么东西时,你可能不会像IOC那样坚持使用其中一种技术。一方面我没有看到ISomeDomainModelEntityViewModel,ISomeWindowViewModel和IObservableCollection的好处,每个接口只有一个类,除了DI,另一方面,接口对于DI不是必需的。我想你可以看看Prism的例子,看看他们如何使用DI构建ViewModel以及何时使用接口。通常,如果要使用DI构建ViewModel,ViewModel的所有依赖项都是在接口中定义的服务,并使用IOC来解析这些服务。由于这些服务具有外部依赖性,因此模拟这些接口以进行测试很容易。但是,大多数ViewModel都没有接口,因为它们主要由View和其他ViewModel使用。
我认为ViewModel可以包含其他ViewModel,例如主ViewModel包含每个页面的子项。
不明显。除了接口之外,我个人认为将IObservableCollection放入IOC并不是一个好方法。
我个人认为注入IView会破坏MVVM,因为ViewModel不应该知道View。即使是IView,ViewModel也可以引用View。但是在某些情况下,如果ViewModel有一个IView可以让很多事情变得更容易,为什么不呢?正如我所说,架构应该是灵活的。
希望它可以提供帮助。