1

ViewModel、Model、MVVM 架构问题。

曾几何时,我曾经这样定义一个模型类:

public class Person
{
  public string FirstName;
  public string LastName;
}

几年后,我明白最好如下定义模型类:

public class Person
{
  private string firstName;
  private string lastName;

  public string FirstName {get{ return firstName;} set{ return firstName; } }
  public string LastName  {get{ return lastName; } set{ return lastName;  } }
}

为什么..因为通常它允许更多的多功能性,例如:

public class Person
{
  private string firstName;
  private string lastName;

  public string FirstName {get{ return firstName;} private set{ return firstName; } }
  public string LastName  {get{ return lastName; } private set{ return lastName;  } }

  public Person(string firstName, string lastName)
  {
      this.firstName = firstName;
      this.lastName = lastName;
  }
}

几个月后,引入了自动属性,事情再次变得容易:

public class Person
{
  public string FirstName {get; set;}
  public string LastName  {get; set;}
}

多功能性仍然存在:

public class Person
{
  public string FirstName {get; private set;}
  public string LastName  {get; private set;}

  public Person(string firstName, string lastName)
  {
      FirstName = firstName;
      LastName = lastName;
  }
}

如果我们在没有私人二传手的情况下上课,甚至是另一个好东西:

var myInstance = new Person{FirstName = "Che", LastName="Guara"}

到目前为止 - 非常好。

但是现在我们有了另一个 MVVM 真正希望我们使用的演变......(在模型中!)

public class Person : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  private string firstName;
  private string lastName;

  public string FirstName
  {
    get{ return firstName; }
    set
    { 
       firstName = value;
       if(PropertyChanged!=null)
        PropertyChanged(this,new PropertyChangedEventArgs("FirstName");
    } 
  }

  public string LastName
  {
    get{ return lastName; }
    set
    { 
       lastName = value;
       if(PropertyChanged!=null)
        PropertyChanged(this,new PropertyChangedEventArgs("LastName");
    } 
  }
}

所以..好的..它不像以前那么短,但它是可以接受的。

但是,如果模型的演变是某种东西,那么自然..

并且一致认为“不要重复自己”是一个很好的原则。

在许多情况下,我不需要特定的 View-Model 类 - 但并非在所有情况下都需要。

没关系。

为什么改变对以对象为中心的范式的整个态度是错误的?

例如:

publie interface IPersistable
{ 
   Guid Id {get;set;}
   DataAccessLayer Dal {get;set}
   void Persist();
   void Populate();
}

public class Person : INotifyPropertyChanged, IPersistable
{
  public DataAccessLayer Dal;

  private Guid Id;

  public Guid Id
  {
     get {return id;}
     set
     {
    id=value; 
    if(PropertyChanged!=null)
        PropertyChanged(this,new PropertyChangedEventArgs("Id");
     }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private string firstName;
  private string lastName;

  public string FirstName
  {
    get{ return firstName; }
    set
    { 
       firstName = value;
       if(PropertyChanged!=null)
        PropertyChanged(this,new PropertyChangedEventArgs("FirstName");
    } 
  }

  public string LastName
  {
    get{ return lastName; }
    set
    { 
       lastName = value;
       if(PropertyChanged!=null)
        PropertyChanged(this,new PropertyChangedEventArgs("LastName");
    } 
  }

  public void Persist() //assume this is part of IPersistable.
  {
    Dal.Persist(this);
  }

  public void Populate() //assume this is part of IPersistable.
  {
    var t=Populate(Id);
    FirstName = t.Firstname;
    LastName = t.LastName;
  }

}

所以我可以在模块中的某个地方做,例如:

myObj.Persist();

这是一个错误的想法还是一个好主意?好架构还是坏架构?

其中仍然存在关注点分离 - 只是写法不同。

真的让我头疼,将不胜感激您对此的投入。

谢谢。

GY

4

1 回答 1

2

关于INotifyPropertyChanged:MVVM 要求您在 ViewModels 上使用它,因为 WPF 使用此接口在 View 与其DataContext是 MVVM 中的 ViewModel 之间进行数据绑定。除此之外,INPC它只是一个用于通知属性更改的接口,可以在您喜欢的任何地方使用。人们通常认为它不应该在模型中实现,这是错误的,但您也不必这样做。你只需要INPC在你的模型上实现,如果你想在某个地方使用它,可能最常用于处理 ViewModel 中的这些更改。如果您的模型仅因 ViewModel 的操作而发生变化,则无需实施INPC例如。

换句话说:该模型不知道它在 MVVM 模式中使用的事实。

因此,在设计模型时不要过多考虑整个系统:它提供了更改通知:很好,它提供了持久化功能:很好,它是一个完美的 OOP 类。这足以使该模型成为 MVVM 的良好模型。

编辑:

问题不是特定于 MVVM 的 imo。有必要问一下,是否代表一个实体(在这种情况下是一个人)、通知属性更改(同样,INPC 不是 MVVM 特定的)和保持持久性对于一个类来说是太多的关注点。通知和持久化是一种服务功能,您仍然在 Dal 中分离实际逻辑。所以,当然为什么不呢,如果在你的应用程序中单独保存和加载实体是有意义的,你为什么会介意呢?为什么你不应该这样做,你真正关心的是什么?当然,具有两个属性的类会更好,但它总是一个权衡......

简而言之:我认为持有数据、维护数据的持久性和通知更改听起来像是一个很好的工作包,可以放入一个类中。

让我知道这是否令人满意地回答了您的问题。

于 2013-04-10T07:35:15.243 回答