反序列化时,XmlSerializer将元素名称放在属性中

时间:2014-01-16 22:03:42

标签: c# xml serialization

我对.NET XML Serializer有一个问题,我在其中使用不同的XML元素,这些XML元素具有映射到相同类型的不同名称。基本上,对象应该完全相同,但我希望它们有一个字符串或枚举或标识三个可能的元素名称中的哪一个使用的东西。所以这是一个例子:

<Body>
  <MyTypeA>
    <Foo>bar</Foo>
  </MyTypeA>
  <MyTypeB>
    <Foo>bar</Foo>
  </MyTypeB>
</Body>

现在,对于课程,MyTypeAMyTypeB都属于同一类型。例如:

public class Body {
  public MyType MyTypeA { get; set; }
  public MyType MyTypeB { get; set; }
}

public class MyType {
  public string Foo { get; set; }

  [XmlIgnore]
  public MyTypeType { get; set; }
}

public enum MyTypeType
{
  MyTypeA,
  MyTypeB
}

序列化时,它工作正常,因为我总是可以确保在序列化之前正确设置枚举的方式。但是当反序列化它没有被设置时,我不确定是怎么回事。

为了记录,我很遗憾没有设置架构,否则我会以这样的方式构建它,以至于我没有这个问题。

1 个答案:

答案 0 :(得分:0)

如果我理解你的问题,这可能会对你有帮助。只需在第4行写下XML文件路径并试一试。

namespace ConsoleApplication1
{

class Program
{
    //private const string xmlPath = @"C:\Users\Jumast\Desktop\StackOverflowQuestion.xml";
    private const string xmlPath, // put the file path here

    static Body makeBody()
    {
        var instance1 = new MyType() { Category = Category.MyTypeA, Foo = "bar" };
        var instance2 = new MyType() { Category = Category.MyTypeB, Foo = "bar" };
        return new Body(){Instance1 = instance1, Instance2 = instance2};
    }

    static void serializeBody(Body body, string path)
    {
        var ser = new DataContractSerializer(body.GetType(), body.GetType().Name, "");
        using (var w = XmlWriter.Create(path, new XmlWriterSettings() { Indent = true }))
        {
            ser.WriteObject(w, body);
        }
    }

    static Body deseerializeBody(string xmlPath)
    {
        Body deserializedBody;
        var ser = new XmlSerializer(typeof(Body));
        using (Stream stream = File.OpenRead(xmlPath))
        {
            deserializedBody = (Body)ser.Deserialize(stream);
        }
        return deserializedBody;
    }

    static void writeBodyToConsole(Body body)
    {
        Console.WriteLine("Instance1: " + body.Instance1);
        Console.WriteLine("Instance2: " + body.Instance2);
        Console.ReadKey();
    }

    static void Main(string[] args)
    {
        serializeBody(makeBody(), xmlPath);
        writeBodyToConsole(deseerializeBody(xmlPath));
    }
}

public class Body : IXmlSerializable
{
    #region Properties
    public MyType Instance1 { get; set; }
    public MyType Instance2 { get; set; }
    #endregion

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

    public void ReadXml(System.Xml.XmlReader reader)
    {
        reader.ReadStartElement();
        Instance1 = new MyType(reader);
        Instance2 = new MyType(reader);
        reader.ReadEndElement();

    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        Instance1.WriteXml(writer);
        Instance2.WriteXml(writer);
    }
    #endregion
}

public class MyType : IXmlSerializable
{
    #region Fields
    private Category _category;
    #endregion

    #region Constructors
    public MyType()
    {
        _category = Category.nil;
        Foo = string.Empty;
    }
    public MyType(XmlReader reader) { ReadXml(reader);}
    #endregion

    #region Methods
    public override string ToString()
    {
        var sb = new StringBuilder();
        sb.Append(string.Format("Foo = {0}", Foo));
        sb.Append(" , ");
        sb.Append(string.Format("Category = {0}", Category));
        return sb.ToString();
    }
    #endregion

    #region Properties
    public string Foo { get; set; }

    public Category Category
    {
        get { return this._category; }
        set { this._category = value; }
    }
    #endregion

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

    public void ReadXml(System.Xml.XmlReader reader)
    {
        Enum.TryParse(reader.Name, out _category);
        reader.Read();
        Foo = reader.ReadElementContentAsString("Foo", "");
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteStartElement(this.Category.ToString(), "");
        writer.WriteElementString("Foo", Foo);
        writer.WriteEndElement();
    }
    #endregion
}

public enum Category
{
    MyTypeA,
    MyTypeB,
    nil
}
}