加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 在基类中实现IXmlSerializable时如何恢复到’默认’XML序

发布时间:2020-12-15 07:58:54 所属栏目:百科 来源:网络整理
导读:我正在尝试序列化一个继承自实现IXmlSerializable的基类的类. 名为PropertyBag的基类是一个允许动态属性的类(credits to Marc Gravell). 我实现了IXmlSerializable,以便动态属性(存储在Dictionary中)被写为普通的xml元素. 例如 当序列化具有公共属性(非动态)
我正在尝试序列化一个继承自实现IXmlSerializable的基类的类.

名为PropertyBag的基类是一个允许动态属性的类(credits to Marc Gravell).

我实现了IXmlSerializable,以便动态属性(存储在Dictionary中)被写为普通的xml元素.

例如
当序列化具有公共属性(非动态)名称和动态属性Age的类时,我希望它生成以下XML:

<Person>
  <Name>Tim</Name>
  <DynamicProperties>
    <Country>
      <string>USA</string>
    </Country>
  </DynamicProperties>
<Person>

我可以让这个部分在基础PropertyBag类中使用WriteXml的以下实现:

public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteStartElement("DynamicProperties");

        // serialize every dynamic property and add it to the parent writer
        foreach (KeyValuePair<string,object> kvp in properties)
        {
            writer.WriteStartElement(kvp.Key);

            StringBuilder itemXml = new StringBuilder();
            using (XmlWriter itemWriter = XmlWriter.Create(itemXml))
            {
                // serialize the item
                XmlSerializer xmlSer = new XmlSerializer(kvp.Value.GetType());
                xmlSer.Serialize(itemWriter,kvp.Value);                    

                // read in the serialized xml
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(itemXml.ToString());

                // write to modified content to the parent writer
                writer.WriteRaw(doc.DocumentElement.OuterXml);
            }

            writer.WriteEndElement();
        }

        writer.WriteEndElement();
    }

但是,在序列化Person类时,它不再序列化正常(非动态)属性,除非我在Person中覆盖WriteXml方法(我不想这样做).有没有办法在基类中我可以自动添加静态属性?我知道我可以使用反射手动执行此操作,但我想知道.Net Framework中是否有一些内置功能?

解决方法

我花了很多时间使用XmlSerializer(以及其他各种序列化API),我很确定这一点:你做不到.实现IXmlSerializable是全有或全无.

我能想到的最接近的是欺骗并将所有固定属性移动到子对象;这会给你略微不同的xml – 类似于:

<FixedProperties>
   <Name>Tim</Name>
</FixedProperties> 
<DynamicProperties>
  <Country>
    <string>USA</string>
  </Country>
</DynamicProperties>

但我希望它能奏效.您将在基础对象上具有pass-thru属性:

[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
public FixedProperties FixedProps {get;set;}
public string Name {
    get {return FixedProps.Name;}
    set {FixedProps.Name = value;}
}

合理?你也可以将Name标记为[XmlIgnore],但它看起来很冗余.在您的定制序列化方法中,您将使用新的XmlSerializer(typeof(FixedProperties))

编辑:这是一个有效的“序列化”示例:

using System;
using System.ComponentModel;
using System.Xml.Serialization;

static class Program
{
    static void Main()
    {
        MyType obj = new MyType { Name = "Fred" };
        var ser = new XmlSerializer(obj.GetType());
        ser.Serialize(Console.Out,obj);
    }
}
public class MyType : IXmlSerializable
{
    public MyType()
    {
        FixedProperties = new MyTypeFixedProperties();
    }
    [Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
    public MyTypeFixedProperties FixedProperties { get; set; }
    [XmlIgnore]
    public string Name
    {
        get { return FixedProperties.Name; }
        set { FixedProperties.Name = value; }
    }

    System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
    {
        return null;
    }

    void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
    {
        throw new System.NotImplementedException();
    }

    void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteStartElement("DynamicProperties");
        writer.WriteElementString("Foo","Bar");
        writer.WriteEndElement();
        fixedPropsSerializer.Serialize(writer,FixedProperties);
    }
    static readonly XmlSerializer fixedPropsSerializer
        = new XmlSerializer(typeof(MyTypeFixedProperties));

}
[XmlRoot("FixedProperties")]
public class MyTypeFixedProperties
{
    public string Name { get; set; }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读