简体   繁体   English

在C#序列化器中继承多个属性

[英]Inheriting Multiple Properties In C# Serializer

I am working on serializing a class that has left a right properties which are of a base type. 我正在序列化一个具有基本类型的right属性的类。

[Serializable]    
public class MyClass{
    public BaseChild Left {get;set;}
    public BaseChild Right {get;set;}
}

If I serialize this, I get an xml that has something like this: 如果我将其序列化,则会得到一个具有以下内容的xml:

<Left p7:type="InherrittedChild" xmlns:p7=blabla>
   <Property />
</Left>

Are there some options I can set on those properties to make the xml look like this: 我可以在这些属性上设置一些选项以使xml看起来像这样:

<Left>
   <InherittedChild>
       <Property />
   </InherittedChild>
</Left>

Since I have two properties that are the same type, I can't just add the [XmlInclude(typeof(child))] since that would render an ambiguous xml. 由于我具有两个相同类型的属性,因此我不能只添加[XmlInclude(typeof(child))]因为这将导致模棱两可的xml。

Really tricky ... XmlSerialization is not polymorphic so your XML usually provides a flattened version of your object hierarchie. 确实很棘手…… XmlSerialization不是多态的,因此您的XML通常提供对象层次结构的扁平版本。 I see two possible implementations. 我看到了两种可能的实现。 The first exposes the base property as another name (see "ConcreteChild"). 第一个将基础属性公开为另一个名称(请参见“ ConcreteChild”)。 The other implements IXmlSerialization (see "ConcreteChild2") so that you can write your custom nesting of properties. 另一个实现IXmlSerialization(请参见“ ConcreteChild2”),以便您可以编写自定义的属性嵌套。

// Base Class
[Serializable]
[XmlInclude(typeof(ConcreteChild))]
public class BaseChild
{
    public BaseChild()
    {
        ChildName = "Base";
    }

    public String ChildName { get; set; }
}

// Exposing Parent Property
[Serializable]
public class ConcreteChild : BaseChild
{
    public new String ChildName { get; set; }

    public String BaseChildName { 
        get
        {
            return ((BaseChild) this).ChildName;
        }

        set
        {
            ((BaseChild)this).ChildName = value;
        }
    }
}


// Writing Custung Serializable
[Serializable]
public class ConcreteChild2 : BaseChild, IXmlSerializable
{
    public new String ChildName { get; set; }

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

    public void ReadXml(XmlReader reader)
    {
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteStartElement("InherittedChild");
        writer.WriteElementString("ConcreteChildName", ChildName);
        writer.WriteEndElement();

        // Since BaseChild does not implement IXmlSerializable
        // we cannot use base.WriteXml(writer);
        writer.WriteElementString("BaseChildName", ((BaseChild) this).ChildName);
    }
}

[XmlInclude(typeof(ConcreteChild))]
[XmlInclude(typeof(ConcreteChild2))]
[Serializable]
public class MyClass
{
    public BaseChild Left { get; set; }

    [XmlElement("ConcreteChild2", typeof(ConcreteChild2))]  // does not work without !!!
    public BaseChild Right { get; set; }

}

Result: You can see both serializations in the MyClass structure 结果:您可以在MyClass结构中看到两个序列化

<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Left xsi:type="ConcreteChild">
    <ChildName>Left</ChildName>
    <BaseChildName>Base</BaseChildName>
  </Left>
  <ConcreteChild2>
    <InherittedChild>
      <ConcreteChildName>Right</ConcreteChildName>
    </InherittedChild>
    <BaseChildName>Base</BaseChildName>
  </ConcreteChild2>
</MyClass>

Serialization 序列化

var mc = new MyClass();
mc.Left = new ConcreteChild { ChildName = "Left"};
mc.Right = new ConcreteChild2 { ChildName = "Right" };
StringWriter textWriter = new StringWriter();
XmlSerializer xmlSerializer = new XmlSerializer(mc.GetType());
xmlSerializer.Serialize(textWriter, mc);
var s = textWriter.ToString();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM