2013-04-09 31 views
1

我有以下情况。检查GUI模型是否改变;比较两个GUI模型

我有一个复杂的模型(包含许多对象,非原始数据类型)。通过GUI,我允许用户编辑这个模型。

当单击编辑按钮时,我创建一个用户修改的当前模型的克隆,直到他们按下“保存”或“放弃”。

我需要知道克隆模型是否已更改,以及数据是否与原始模型相比发生了变化。这将是检查用户是否更改模型的任何属性的最佳方法。

我在考虑两个选项:

  1. 重写equals和GetHashCode和落实每个类的模型对象部分的IEquatable接口(将是一个很大的工作在这种情况下做的) 。

  2. 使用脏标志。

  3. 我看到了一些INotifyPropertyChanged接口的实现。

我不认为选项2和3个是有效的选择,因为用户可以修改一个属性,然后设置回原始值。(这样的模型没有真正改变)。

还有其他posibliies?

感谢,

+2

我知道你问的是最好的方式,但如果你想要一个快速而又快速的解决方案,如果所有的对象都是可序列化的,你可以序列化原始的,克隆和比较e产生的字符串。我认为正确的方法是实现'IEquatable'和'INotifyPropertyChanged',并且每次属性改变时,比较它是否与原始文件不同。 – 2013-04-09 11:28:40

+0

Lemme问你另一件事:你正在使用哪种版本的.NET Framework和C#? – 2013-04-09 11:45:26

+0

@ConradClark我正在使用.NEt框架4.5 Visual Studio 2012 – 2013-04-09 11:52:17

回答

1

这是一种选择,假设你的模型是序列化(低于Convert any object to a byte[]找到方法)

byte[] ObjectToByteArray(Object obj) 
{ 
    if (obj == null) 
     return new byte[]{}; 
    BinaryFormatter bf = new BinaryFormatter(); 
    MemoryStream ms = new MemoryStream(); 
    bf.Serialize(ms, obj); 
    return ms.ToArray(); 
} 

然后,如果你的模型是非常巨大的,它可以损害性能,并且您可以使用不安全的代码,请使用此处找到的比较器Comparing two byte arrays in .NET

static unsafe bool UnsafeCompare(byte[] a1, byte[] a2) 
    { 
     if (a1 == null || a2 == null || a1.Length != a2.Length) 
      return false; 
     fixed (byte* p1 = a1, p2 = a2) 
     { 
      byte* x1 = p1, x2 = p2; 
      int l = a1.Length; 
      for (int i = 0; i < l/8; i++, x1 += 8, x2 += 8) 
       if (*((long*)x1) != *((long*)x2)) return false; 
      if ((l & 4) != 0) { if (*((int*)x1) != *((int*)x2)) return false; x1 += 4; x2 += 4; } 
      if ((l & 2) != 0) { if (*((short*)x1) != *((short*)x2)) return false; x1 += 2; x2 += 2; } 
      if ((l & 1) != 0) if (*((byte*)x1) != *((byte*)x2)) return false; 
      return true; 
     } 
    } 

否则,您可以使用更简单,但速度慢(在同一个问题找到)

static bool ByteArrayCompare(byte[] a1, byte[] a2) 
{ 
    IStructuralEquatable eqa1 = a1; 
    return eqa1.Equals(a2, StructuralComparisons.StructuralEqualityComparer); 
} 

下面是一个例子使用模式:

[Serializable] 
    class House 
    { 
     public Size Size{get;set;} 
    } 

    [Serializable] 
    class Size 
    { 
     public double Width { get; set; } 
     public double Length { get; set; } 
     public double Height { get; set; } 
    } 

然后比较你的对象:

House house = new House() 
{ 
    Size = new Size() 
    { 
     Width = 10 
    } 
}; 
House house2 = new House() 
{ 
    Size = new Size() 
    { 
     Width = 20 
    } 
}; 
House equal = new House() 
{ 
    Size = new Size() 
    { 
     Width = 10 
    } 
}; 

Debug.Assert(UnsafeCompare(ObjectToByteArray(house), ObjectToByteArray(equal))); 
Debug.Assert(!UnsafeCompare(ObjectToByteArray(house), ObjectToByteArray(house2))); 

Debug.Assert(ByteArrayCompare(ObjectToByteArray(house), ObjectToByteArray(equal))); 
Debug.Assert(!ByteArrayCompare(ObjectToByteArray(house), ObjectToByteArray(house2)));