MVVM和DI - 如何处理Model对象?

时间:2010-07-27 15:34:52

标签: c# .net wpf mvvm caliburn

我正在使用Caliburn和C#,但我觉得这是一个通用的MVVM / DI问题。

假设我有一个视图模型NoteViewModel,它传递了一个名为Note的模型对象。

以下是一些代码:

class NoteViewModel : PropertyChangedBase
{
  private readonly Note _note;

  public NoteViewModel(Note note)
  {
    _note = note;
  }

  public string Title
  { 
    get { return _note.Title; } 
    set { _note.Title = value; NotifyOfPropertyChange(() => Title); }
  }
}

现在,通过调用new()并传递模型对象来创建此对象。

嗯,这很好用,但现在我需要添加一个需要从我的DI容器中导入类的方法。

那么我只是调用ServiceLocator.Current.GetInstance()来获取它吗?或者我应该设计这个通过DI容器创建的视图模型,并以某种方式设置传递Note对象的方法?

设计此视图模型的正确方法是什么?基本上是一个“PerInstance”视图模型,需要一个模型对象才能使用它。 Caliburn有内置的方法吗?

3 个答案:

答案 0 :(得分:3)

Caliburn有一个接口(IHaveSubject及其类型化版本IHaveSubject)解决了这种情况:基本上它允许在实例化之后用一个“主题”配置ViewModel,通过容器:

class NoteViewModel : PropertyChangedBase, IHasSubject<Note> {
  ...   
} 

myNoteViewModel = ... //obtain an instance
myNoteViewModel.WithSubject(new Note());

此解决方案还与ISubjectSpecification / Conductor很好地集成 基础设施。

尽管构造后初始化是一种简单而有效的解决方案,但您可能不希望(从纯设计角度)放弃使用显式构造函数参数来强制需要使用Note来实现ViewModel。 在这种情况下,我认为你必须利用你的DI容器的特殊功能,因为你可能有一些构造函数的参数代表一个“真正的”输入参数,而其他参数可能是服务依赖。

例如,Castle Windsor有一个很好的功能,允许您快速为ViewModel构建一个显式(类型)工厂;工厂方法只允许设置“真实”参数,而所有依赖项都由容器管理(有关此温莎功能的详细说明,请参阅此文章:http://kozmic.pl/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx

答案 1 :(得分:0)

你能用分层视图模型解决它吗?

对我来说,在构建更大的应用程序时,每个模型项目或集合每个View 一个ViewModel需要一个ViewModel变得越来越清晰。

这样我们就可以分层次地构建ViewModels,匹配XAML层次结构。

然后,应用程序的主视图模型可以在顶层定义或注入所需的对象。然后,嵌套视图模型可以按照您设计的方式访问任何内容,以使其可以通过它们访问。

关于Caliburn,我不知道有关该框架的任何具体事情,抱歉。

答案 2 :(得分:0)

我也在使用ServiceLocator。这样做我也“感到很脏”。但是我已经决定使用YAGNI原则并保持这种模式,直到我发现向我的构造函数中添加5个IServices的复杂性,通过3-4层继承将它们传递给需要它们的基类,并通过容器创建一切。当然我的应用程序正在发展,YAGNI并不总是持续......