仅序列化对象的已更改属性

时间:2015-06-19 06:09:41

标签: c# serialization reflection xml-serialization

在C#中,是否可以仅使用修改后的值序列化对象?

例如:我将Button对象的实例绑定到PropertyGrid中,并且我希望仅使用已更改的属性序列化该Button对象。在C#中存档的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

在您自己的类型中:是的,您可以通过ShouldSerialize*模式支持此功能,例如:

public string Name {get;set;}
public bool ShouldSerializeName() { return Name != null; }

但是,在外部类型上 - 完全取决于他们是否支持此类型。请注意,这也将告诉属性网格要包含哪些内容。

在某些情况下,[DefaultValue({the default value})]也会有效。

答案 1 :(得分:1)

您可以通过反射迭代对象的属性,将其属性与“新鲜”实例进行比较,并以某种方式记下差异。但是如果你选择那个路径,你应该解决很多问题,比如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>

答案 2 :(得分:0)

从您提供的信息中突然出现。

首先需要在对象中找到脏属性,当其他属性发生更改时,您可以拥有另一个项目并跟踪它。或每个属性的isdirty属性,或者如果您可以将旧对象与新对象进行比较。

然后在ToString()方法或自定义序列化方法中,覆盖以仅使用更改的属性生成序列化对象自定义。

它适用于POCO对象,因为您制作的复杂按钮对象必须查看如何操作。

它的正义和想法,如果有代码样本,则更多。