【问题标题】:Serialize only changed properties of the object仅序列化对象的更改属性
【发布时间】:2015-06-19 06:09:40
【问题描述】:

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

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

【问题讨论】:

  • 仅具有更改属性的对象 - 不清楚您的期望。你能添加一个代码示例吗?
  • 您如何找出更改的属性?
  • 简短的回答是否定的,但看看stackoverflow.com/questions/9377414/…
  • 这里更改的属性表示不在其默认值中的值。例如,在 Button 对象中,“Cursor”的默认值为“Default”。如果我将其更改为其他值(例如:SizeAll),我需要将该更改转换为 XML。默认值中的所有其他属性可能不在该 XML 中。

标签: c# serialization reflection xml-serialization


【解决方案1】:

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

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

然而,在 external 类型上——他们是否支持这一点完全取决于他们。请注意,这也会告诉属性网格要加粗。

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      出乎意料,根据您​​提供的信息。

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

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

      它适用于 POCO 对象,对于复杂的按钮对象,你必须看看如何去做。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-24
        • 2013-02-12
        • 1970-01-01
        • 2019-08-13
        • 1970-01-01
        • 1970-01-01
        • 2012-11-14
        相关资源
        最近更新 更多