我应该使用DTO作为MVVM中的数据模型吗?

时间:2010-04-27 10:21:42

标签: wpf architecture mvvm dto

我目前正在研究使用MVVM的第一次真正的尝试,并且已经阅读了有关如何最好地实现它的各种文章。

我目前的想法是将我的数据模型有效地用作数据传输对象,使它们可序列化并使它们存在于客户端和服务器端。 这似乎是一个合乎逻辑的步骤,因为两个对象类型实际上只是属性getter和setter的集合,而介于两者之间的另一层看起来像是完全矫枉过正。

显然,INotifyPropertyChanged在服务器端无法正常工作会出现问题,因为没有要与之通信的ViewModel,但只要我们小心从服务层中的数据模型构建正确的域模型对象而不是处理服务器端的数据模型我不认为这应该是一个大问题。

我在阅读中没有找到太多关于这种方法的信息,所以我想知道这是否是一个非常标准的事情,这只是假设是在多层中做MVVM的事实上的方式环境? 如果我对事情有完全错误的想法那么对其他方法的想法也会受到赞赏。

3 个答案:

答案 0 :(得分:5)

您可以使用您认为合适的任何型号,是的,您的所有属性都需要INotifyPropertyChanged行为。这将如何影响服务层完全取决于您的实现。

我假设您在视图中绑定了DTO?

我如何看待应用程序各层之间存在阻抗不匹配,即你的 域模型可能看起来与您的关系模型相似,但有微妙但重要的差异。还有 域模型和DTO之间的不匹配(对象可能是扁平的,计算的属性等,......)。直接绑定到DTO是很诱人的,因为它们可能被设计为具有您对特定操作所需的内容,但是在DTO和视图所需的内容之间也存在阻碍不匹配以实现所需的结果。这是视图模型的用武之地。视图模型负责将DTO属性代理到视图,它负责让视图知道是否存在验证错误,并将命令路由到适当的处理程序(保存,删除等) ,...)。

我倾向于以下列方式进行设置:

// POCO object. Serializable.
public class AddressDto 
{    
   public int Id { get; set; }
   public string Street { get; set; }    
   public string City { get; set; }    
   public string Country { get; set; } 
}

// IDataErrorInfo for validation.
public class AddressViewModel : INotifyPropertyChanged, IDataErrorInfo
{
   private readonly AddressDto addressDto;

   public AddressViewModel(AddressDto addressDto)
   {
      this.addressDto = addressDto;      
   }

   public int Id { /* get and set for property changed event and update dto */ }
   public string Street { /* get and set for property changed event and update dto  */ }
   public string City { /* get and set for property changed event and update dto  */ }
   public string Country { /* get and set for property changed event and update dto  */ }
   ...

   // IDataErrorInfo implementation
}

public class EditAddressViewModel : INotifyPropertyChanged
{
   public AddressViewModel Address { /* get and set for property changed event */ }
   public ICommand Save { /* setup command */ }
   public ICommand Cancel { /* setup command */ }

   private void Save()
   {
   }

   private void Cancel()
   {
   }
}

然后,您的EditAddressView将绑定到EditAddressViewModel。基本上,规则是您的所有UI行为都应该根据您的视图模型来表达。

是的,这确实意味着额外的工作,但是你可以做些事情来简化一些事情(代码生成等)。我实际上正在开发一个库,旨在使用流畅的api简化整个MVVM进程。请查看http://fluentviewmodel.codeplex.com/

答案 1 :(得分:2)

我不是这方面的专家。我有同样的情况。我同意你的观点,这太过分了。我已经使用这个解决方案很长一段时间了,并没有遇到任何问题。 INotifyPropertyChanged对我来说不是一个大问题,因为服务器端的任何内容都不会订阅PropertyChanged事件。如果要在数据模型上使用继承,那么所有都必须是可序列化的。在我的场景中,我的数据模型有两个基类:一个用于数据传输,另一个不用。

答案 2 :(得分:1)

我决定在我的ViewModel上有一个属性“Model”。在模型本身中,我已经实现了IPropertyNotifyChanged和IDataErrorInfo。因此,在我的ViewModel中,我跳过属性,其中代码将简单地“落入”模型。相反,View直接绑定到这些属性的模型。

对于更复杂的情况,我必须调整模型中的数据以适合视图,我在ViewModel中执行此操作。此外,命令等在ViewModel中。但我没有看到在ViewModel中使用样板代码重复我在模型中已经存在的相同内容的原因。