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

本文关键字:属性 序列化 对象 | 更新日期: 2023-09-27 17:57:15

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

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

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

在您自己的类型中: 是的,你可以支持这一点 - 通过ShouldSerialize*模式,例如:

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

但是,在外部类型上 - 他们是否支持这完全取决于他们。请注意,这也会告诉属性网格要加粗哪些。

在某些情况下,[DefaultValue({the default value})]也可以工作。

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

出乎意料的是,从你提供的信息来看。

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

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

它适用于POCO对象,对于复杂的按钮对象,您必须查看如何做到这一点。

它只是和想法,如果有代码示例,则更多。