此方法基于此线程中提供的一组不同概念。我想我会把它放在那里给任何正在寻找一种干净有效的方法的人,就像我自己一样。
这种混合概念的关键在于:
- 您不想复制数据以避免膨胀和资源占用;
- 您想知道对象的属性何时从给定的原始/干净状态更改;
- 您希望 IsDirty 标志既准确又需要很少的处理时间/功率来返回值;和
- 您希望能够告诉对象何时再次认为自己是干净的。这在 UI 中构建/工作时特别有用。
鉴于这些要求,这就是我想出的,它似乎对我来说非常有效,并且在处理 UI 和准确捕获用户更改时变得非常有用。我还在下面发布了“如何使用”,向您展示我如何在 UI 中使用它。
物体
public class MySmartObject
{
public string Name { get; set; }
public int Number { get; set; }
private int clean_hashcode { get; set; }
public bool IsDirty { get { return !(this.clean_hashcode == this.GetHashCode()); } }
public MySmartObject()
{
this.Name = "";
this.Number = -1;
MakeMeClean();
}
public MySmartObject(string name, int number)
{
this.Name = name;
this.Number = number;
MakeMeClean();
}
public void MakeMeClean()
{
this.clean_hashcode = this.Name.GetHashCode() ^ this.Number.GetHashCode();
}
public override int GetHashCode()
{
return this.Name.GetHashCode() ^ this.Number.GetHashCode();
}
}
它很简单,可以满足我们所有的要求:
- 脏检查的数据不会重复...
- 这考虑了所有属性更改方案(请参阅下面的方案)...
- 当您调用 IsDirty 属性时,会执行一个非常简单且小型的 Equals 操作,并且可以通过 GetHashCode 覆盖完全自定义...
- 通过调用 MakeMeClean 方法,您现在又拥有了一个干净的对象!
当然,您可以对其进行调整以包含一堆不同的状态……这完全取决于您。此示例仅显示如何进行正确的 IsDirty 标志操作。
场景
让我们回顾一下这个场景,看看会发生什么:
如何使用,一个 WinForms UI 示例
这只是一个示例,您可以通过 UI 以多种不同的方式使用它。
假设您有两种形式([A] 和 [B])。
第一个([A]) 是您的主表单,第二个([B]) 是一个允许用户更改 MySmartObject 中的值的表单。
[A] 和 [B] 表单都声明了以下属性:
public MySmartObject UserKey { get; set; }
当用户单击 [A] 表单上的按钮时,会创建 [B] 表单的实例,设置其属性并显示为对话框。
表单 [B] 返回后,[A] 表单根据 [B] 表单的 IsDirty 检查更新其属性。像这样:
private void btn_Expand_Click(object sender, EventArgs e)
{
SmartForm form = new SmartForm();
form.UserKey = this.UserKey;
if(form.ShowDialog() == DialogResult.OK && form.UserKey.IsDirty)
{
this.UserKey = form.UserKey;
//now that we have saved the "new" version, mark it as clean!
this.UserKey.MakeMeClean();
}
}
此外,在 [B] 中,当它正在关闭时,您可以检查并提示用户是否正在关闭其中未保存更改的表单,如下所示:
private void BForm_FormClosing(object sender, FormClosingEventArgs e)
{
//If the user is closing the form via another means than the OK button, or the Cancel button (e.g.: Top-Right-X, Alt+F4, etc).
if (this.DialogResult != DialogResult.OK && this.DialogResult != DialogResult.Ignore)
{
//check if dirty first...
if (this.UserKey.IsDirty)
{
if (MessageBox.Show("You have unsaved changes. Close and lose changes?", "Unsaved Changes", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
e.Cancel = true;
}
}
}
正如您从上面的示例中看到的那样,这可能是一件非常有用的事情,因为它确实简化了 UI。
注意事项
- 每次实现此功能时,您都必须将其自定义为您正在使用的对象。例如:不使用反射就没有“简单”的通用方法......如果使用反射,您会失去效率,尤其是在大型和复杂的对象中。
希望这可以帮助某人。