1

我有以下情况。

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

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

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

我在这里考虑两种选择:

  1. 覆盖 Equals 和 GetHashCode 并为模型的每个对象类部分实现 IEquatable 接口(在这种情况下需要做很多工作)。

  2. 使用脏标志。

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

我不认为选项 2 和 3 是有效选项,因为用户可能会修改一个属性,然后将其设置回原始值。(因此模型并没有真正改变)。

还有其他可能性吗?

谢谢,

4

1 回答 1

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)));
于 2013-04-09T12:06:10.310 回答