测试对象的更改

时间:2010-03-26 15:34:52

标签: c# comparison

我有一个应用程序需要确定用户是否对对象进行了更改。因此,当首次加载对象时,我创建一个深层副本(使用序列化/反序列化)并将副本保存到单独的字段中。副本变为myCurrentObject,原始变为myOriginalObject

现在我需要对myCurrentObject进行更改测试,我计划将其与myOriginalObject进行比较。我只需要boolean结果,表明是否进行了任何更改。我已经确定一个简单的哈希码比较不起作用。 GetHashCode()会为两个对象生成不同的结果,即使没有更改也是如此。

我正准备编写一个方法来进行逐个属性的比较,但在此之前,我想我会检查是否有更简单,更可重用的方法来测试myCurrentObject看看它是否已从myOriginalObject更改。

有什么建议吗?谢谢你的帮助。

6 个答案:

答案 0 :(得分:5)

相反,您可以在每个属性上实现OnPropertyChanged事件,然后您就可以看到是否抛出了该事件。如果您专门实现了INotifyPropertyChanged,那么您将获得额外的好处,即如果您愿意,可以执行WPF绑定。

如果无法做到这一点,您可能会实现一个带有反射的解决方案,该解决方案将遍历两个寻找差异的对象。

答案 1 :(得分:2)

答案 2 :(得分:2)

  1. 您可以覆盖GetHashCode方法以反映您的需求。
  2. 哈希码只能告诉你一个对象肯定已经改变,它无法告诉你一个对象肯定没有改变(因为不同的对象可以返回相同的哈希码)。
  3. 调查Object.Equals方法

答案 3 :(得分:1)

您可以添加一个脏标志,指示任何字段已更改。在属性集中设置脏标志。

public bool IsDirty { get { return m_IsDirty; } }
public string Name {
    set
    {
        m_Name = value;
        m_IsDirty = true;
    }
}   

答案 4 :(得分:0)

我通常会做这样的测试:

public string sodomizar(myObject object)
{
   return object.prop1.ToString() + object.prop2.ToString();
}

然后测试:

if(sodomizar(object1)==sodomizar(object2))
{
doStuff();
}

答案 5 :(得分:0)

我会考虑使用包含两件事的抽象超类:

  • 一个标志,声明是否'跟踪 更改'是否开启(默认为 假)
  • 一个字典实例 包含键控值历史记录

...然后在您感兴趣的每个属性访问器中调用Base.TrackChange(string,object)。传递的字符串是Property的名称(使用反射/从堆栈跟踪中拉出属性名称: - 表示每个方法中的代码可以完全相同)...并且传递的对象只是元变量'value ”。一些仔细的反射/堆栈跟踪检查可能意味着您可以删除此方法上的字符串参数...意味着您将实体C#编码要求保持在最低限度。

该标志位于那里,因为对象的基本状态初始化意味着可以进行属性更改(设置访问器调用),直到对象第一次完全水合。

字典是否可以跟踪更改(审计?)等等。如果您在'IsDirty'问题上所需要的只是简单的真/假,则将其缩放回第二个布尔值。

类似的东西:

public abstract Class EntityBase
{
    private bool _changesAreTracking = false;
    private Dictionary<string, object> _changes = null;
    public EntityBase() {}

    public TrackChange(string propertyName, object value)
    {
        if(_changesAreTracking)
        {
            if(_changes == null) { _changes = new Dictionary<string, object>(); }

            _changes.Add(propertyName, value);
        }
    }

    public void StartTrackChanges()
    {
        _changesAreTracking = true;
    }

    public bool HasChanged()
    {
        bool returnThis = false;

        if(_changes != null && _changes.Keys.Count() > 0)
        {
            returnThis = true;
        }

        return returnThis;
    }

    public bool HasChanged(string propertyName)
    {
        bool returnThis = false;

        if(_changes != null && _changes.Keys.Contains(propertyName))
        {
            returnThis = true;
        }

        return returnThis;
    }
}