【问题标题】:Should I use DTOs as my data models in MVVM?我应该在 MVVM 中使用 DTO 作为我的数据模型吗?
【发布时间】:2011-02-12 19:14:46
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: wpf architecture mvvm dto


    【解决方案1】:

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

    对于更复杂的情况,我必须调整模型中的数据以适应视图,我在 ViewModel 中执行此操作。此外,命令等都在 ViewModel 中。但我看不出有什么理由让 ViewModel 中的样板代码重复我在模型中已有的东西。

    【讨论】:

      【解决方案2】:

      您可以使用任何您觉得舒服的模型,是的,您的所有属性都需要 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/

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 谢谢,目前似乎没有真正明确的共识。鉴于您之前做过类似的事情,没有任何问题,我会接受这个作为答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-27
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        • 1970-01-01
        • 2018-03-13
        • 2012-02-06
        相关资源
        最近更新 更多