【问题标题】:Custom XML serialization with inheritance具有继承的自定义 XML 序列化
【发布时间】:2011-03-02 16:19:00
【问题描述】:

我有以下要序列化的类结构:

    [XmlRoot("SomeClass")]
public class SomeClass
{
    private BaseClass[] _itemArray;
    public BaseClass[] ItemArray
    {
        get { return _itemArray; }
        set { _itemArray = value; }
    }

    public PPSPStatReportMessage()
        : base()
    {
    }
}

public class SomeOtherClass
{
    private int _property5;
    [XmlAttribute("Property5")]
    public int Property5
    {
        get { return _property5; }
        set { _property5 = value; }
    }

    private string _property6;
    [XmlText()]
    public string Property6
    {
        get { return _property6; }
        set { _property6 = value; }
    }

    public SomeOtherClass()
    {
    }
}

[XmlInclude(typeof(DerivedClass1))]
[XmlInclude(typeof(DerivedClass2))]
[XmlRoot("BaseClass")]
[XmlType("")]
public class BaseClass
{
    private string _property1;
    [XmlAttribute("Property1")]
    public string Property1
    {
        get { return _property1; }
        set { _property1 = value; }
    }

    public SomeClass(string PropertyVal)
    {
        _property1 = PropertyVal;
    }
}

[XmlRoot("BaseClass")]
[XmlTypeAttribute(Namespace = "")]
public class DerivedClass1 : BaseClass
{
    private string _property2;
    [XmlAttribute("Property2")]
    public string Property2
    {
        get { return _property2; }
        set { _property2 = value; }
    }


    private SomeOtherClass _property3;
    [XmlElement("SomeOtherClass")]
    public SomeOtherClass Property3
    {
        get { return _property3; }
        set { _property3 = value; }
    }

    public DerivedClass()
        : base("PropertyVal1")
    {
    }
}

[XmlRoot("BaseClass", Namespace = "")]
[XmlType("")]
public class DerivedClass2 : BaseClass
{
    private Int64 _property4;
    [XmlAttribute("Property4")]
    public Int64 Property4
    {
        get { return _property4; }
        set { _property4 = value; }
    }

    public DerivedClass2()
        : base("PropertyVal2")
    {
    }
}

这是我用来序列化 SomeClass 的方法:

public static string SerializeXML(object Value, System.Type ObjectType)
    {
        XmlSerializer serializer = new XmlSerializer(ObjectType);
        XmlSerializerNamespaces namespaceSerializer = new XmlSerializerNamespaces();
        namespaceSerializer.Add("", "");
        StringWriter ms = new StringWriter();
        serializer.Serialize(ms, Value, namespaceSerializer);
        return ms.ToString();
    }

此方法生成如下所示的 XML 结构:

<?xml version="1.0" encoding="utf-16"?>
<SomeClass>
  <ItemArray>
    <BaseClass d3p1:type="DerivedClass1" Property1="PropertyVal1" Property2="123" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">
      <SomeOtherClass Property5="0" >STRING DATA</SomeOtherClass>
    </BaseClass>
    <BaseClass d3p1:type="DerivedClass2" Property="PropertyVal2" Property4="456" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance" />
  </ItemArray>
</SomeClass>

但是,我需要省略 d3p1:type 和 xmlns:d3p1 属性并生成如下所示的 XML 结构:

<?xml version="1.0" encoding="utf-16"?>
<SomeClass>
  <ItemArray>
    <BaseClass Property1="PropertyVal1" Property2="123">
      <SomeOtherClass Property5="0" >STRING DATA</SomeOtherClass>
    </BaseClass>
    <BaseClass Property="PropertyVal2" Property4="456" />
  </ItemArray>
</SomeClass>

正如您在代码中看到的,我尝试使用 XmlType 和 XmlTypeAttribute,但没有成功。

关于如何生成上述 XML 结构的任何建议(没有 d3p1:type 和 xmlns:d3p1 属性)?

【问题讨论】:

  • XmlSerializer.Deserialize 需要它才能正常工作。你从不反序列化吗?
  • 我正在序列化,但我检查“属性”属性以了解将使用哪种对象类型进行反序列化。

标签: c# xml serialization inheritance


【解决方案1】:

您是否需要将子类元素称为“BaseClass” - 或者派生类的名称是否需要?

我正在序列化类似的子类结构,并且还想摆脱“d3p1:type”和“xmlns:d3p1”标签——而是用派生类标签替换“BaseClass”标签。因此可以为您的示例生成 xml:

<ItemArray>
    <DerivedClass1 Property1="PropertyVal1" Property2="123">
        ....
    </DerivedClass1>

您在 BaseClass 上使用 XmlInclude 属性来让 serliazer 知道期望哪些派生类。相反,您可以告诉序列化程序每个元素的预期子类型:

public class SomeClass
{
    private BaseClass[] _itemArray;

    [XmlElement(typeof(DerivedClass1))]
    [XmlElement(typeof(DerivedClass2))]
    public BaseClass[] ItemArray
    { 
        get { return _itemArray; }
        set { _itemArray = value; }
}

消除“类型”属性。反序列化也可以正常工作。

【讨论】:

    【解决方案2】:

    你不能直接完成你想要的。

    如果被序列化的类型不是包含的确切类型,.NET 必须跟踪该类型的真正含义以允许正确的反序列化。

    要完成您想要的 - 使用 RegEx.Replace() 或其他后处理来替换命名空间。

    (例如,序列化实际上是 String 的 Object 会导致此问题)。

    【讨论】:

      【解决方案3】:
      XmlWriterSettings settings = new XmlWriterSettings();
      settings.OmitXmlDeclaration = true;
      settings.Indent = true;
      
      using (XmlWriter writer = XmlWriter.Create(file, settings))
      {
          XmlSerializer serializer = new XmlSerializer(source.GetType());
      
          XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
          namespaces.Add(string.Empty, string.Empty);
          // ...
      }
      

      【讨论】:

      • 您好,感谢您的回复。我尝试使用 XmlWriter,但它给出了相同的结果(即:仍然有 xmlns 并输入生成的 xml)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多