仅序列化对象的更改属性
Serialize only changed properties of the object
在 C# 中是否可以仅使用修改后的值序列化对象?
例如:我将 Button 对象的实例绑定到 PropertyGrid 中,我想用仅更改的属性序列化该 Button 对象。在 C# 中,最好的存档方法是什么?
从你提供的信息来看,出乎意料。
您首先需要找到对象中的脏属性,您可以有另一个项目并在其他属性发生变化时跟踪它。或每个属性 isdirty 属性,或者如果您可以将旧对象与新对象进行比较。
然后在 ToString() 方法或您自定义的序列化方法中,重写以仅使用更改的属性生成自定义的序列化对象。
它适用于POCO对象,对于你制作的复杂按钮对象,你必须看看如何去做。
它的公正和想法,如果有代码示例会更多。
您可以通过反射迭代对象的属性,将其属性与 'fresh' 实例进行比较,并以某种方式记下差异。但是,如果您选择该路径,您应该解决许多问题,例如 null
处理、序列化不可序列化类型、序列化引用等。这里只是一个草图:
public static string ChangedPropertiesToXml<T>(T changedObj)
{
XmlDocument doc=new XmlDocument();
XmlNode typeNode = doc.CreateNode(XmlNodeType.Element, typeof (T).Name, "");
doc.AppendChild(typeNode);
T templateObj = Activator.CreateInstance<T>();
foreach (PropertyInfo info in
typeof (T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (info.CanRead && info.CanWrite)
{
object templateValue = info.GetValue(templateObj, null);
object changedValue = info.GetValue(changedObj, null);
if (templateValue != null && changedValue != null && !templateValue.Equals(changedValue))
{
XmlElement elem = doc.CreateElement(info.Name);
elem.InnerText = changedValue.ToString();
typeNode.AppendChild(elem);
}
}
}
StringWriter sw=new StringWriter();
doc.WriteContentTo(new XmlTextWriter(sw));
return sw.ToString();
}
来电:
Button b = new Button();
b.Name = "ChangedName";
Console.WriteLine(SaveChangedProperties(b));
一次输出:
<Button>
<Name>ChangedName</Name>
</Button>
在你自己的类型中:是的,你可以支持这个 - 通过 ShouldSerialize*
模式,例如:
public string Name {get;set;}
public bool ShouldSerializeName() { return Name != null; }
然而,在 外部 类型上——是否支持这个完全取决于他们。请注意,这也会告诉 属性-grid 哪个要加粗。
在某些情况下,[DefaultValue({the default value})]
也可以。
在 C# 中是否可以仅使用修改后的值序列化对象?
例如:我将 Button 对象的实例绑定到 PropertyGrid 中,我想用仅更改的属性序列化该 Button 对象。在 C# 中,最好的存档方法是什么?
从你提供的信息来看,出乎意料。
您首先需要找到对象中的脏属性,您可以有另一个项目并在其他属性发生变化时跟踪它。或每个属性 isdirty 属性,或者如果您可以将旧对象与新对象进行比较。
然后在 ToString() 方法或您自定义的序列化方法中,重写以仅使用更改的属性生成自定义的序列化对象。
它适用于POCO对象,对于你制作的复杂按钮对象,你必须看看如何去做。
它的公正和想法,如果有代码示例会更多。
您可以通过反射迭代对象的属性,将其属性与 'fresh' 实例进行比较,并以某种方式记下差异。但是,如果您选择该路径,您应该解决许多问题,例如 null
处理、序列化不可序列化类型、序列化引用等。这里只是一个草图:
public static string ChangedPropertiesToXml<T>(T changedObj)
{
XmlDocument doc=new XmlDocument();
XmlNode typeNode = doc.CreateNode(XmlNodeType.Element, typeof (T).Name, "");
doc.AppendChild(typeNode);
T templateObj = Activator.CreateInstance<T>();
foreach (PropertyInfo info in
typeof (T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (info.CanRead && info.CanWrite)
{
object templateValue = info.GetValue(templateObj, null);
object changedValue = info.GetValue(changedObj, null);
if (templateValue != null && changedValue != null && !templateValue.Equals(changedValue))
{
XmlElement elem = doc.CreateElement(info.Name);
elem.InnerText = changedValue.ToString();
typeNode.AppendChild(elem);
}
}
}
StringWriter sw=new StringWriter();
doc.WriteContentTo(new XmlTextWriter(sw));
return sw.ToString();
}
来电:
Button b = new Button();
b.Name = "ChangedName";
Console.WriteLine(SaveChangedProperties(b));
一次输出:
<Button>
<Name>ChangedName</Name>
</Button>
在你自己的类型中:是的,你可以支持这个 - 通过 ShouldSerialize*
模式,例如:
public string Name {get;set;}
public bool ShouldSerializeName() { return Name != null; }
然而,在 外部 类型上——是否支持这个完全取决于他们。请注意,这也会告诉 属性-grid 哪个要加粗。
在某些情况下,[DefaultValue({the default value})]
也可以。