经过对此事的更多思考,我得出的结论是,至少对于小规模实施而言,最好的方法是编写一个“按值深拷贝”方法,该方法复制对象字段和属性的值而不替换对象本身(这样即使恢复数据,对已编辑对象的任何引用仍保持不变)。
为此,我编写了以下扩展方法:
public static void CopyDataTo(this Object source, Object target) {
// Recurse into lists
if (source is IList) {
var a = 0;
foreach (var item in (IList)source) {
if (a >= ((IList)target).Count) {
var type = item.GetType();
var assembly = Assembly.GetAssembly(type);
var newItem = assembly.CreateInstance(type.FullName);
((IList)target).Add(newItem);
}
item.CopyDataTo(((IList)target)[a]);
a++;
}
while (a < ((IList)target).Count) {
((IList)target).RemoveAt(a);
}
}
// Copy over fields
foreach (var field in source.GetType().GetFields())
field.SetValue(target, field.GetValue(source));
// Copy properties
foreach (var property in source.GetType().GetProperties().Where(
property => property.CanWrite && !property.GetMethod.GetParameters().Any()))
{
property.SetValue(target, property.GetValue(source));
}
}
这不是灵丹妙药:它只适用于相同类型的对象,列表项必须有一个无参数的构造函数,并且无法控制递归深度。此外,我还没有机会在任何长期或更复杂的场景中进行测试,但到目前为止它做了它应该做的(在对象之间复制值)并且可以用于简单的备份/恢复场景:
var backup = new TypeOfVariableToEdit();
data.CopyDataTo(backup);
var clickedOK = RunDataEditor(data);
if (!clickedOK)
backup.CopyDataTo(data);