簡體   English   中英

如何從XML反序列化抽象類的具體實現

[英]How to deserialize concrete implementation of abstract class from XML

我有一個抽象類,有幾個具體的實現。 這需要序列化為XML才能發送到另一個系統 - 這很好。 但是,我還需要能夠反序列化相同的XML結構。 無論我嘗試什么,我似乎都無法做到這一點。 我的班級結構如下:

抽象類:

[XmlIncludeAttribute(typeof(ConcreteFooOne))]
[XmlIncludeAttribute(typeof(ConcreteFooTwo))]
[XmlIncludeAttribute(typeof(ConcreteFooThree))]
[XmlRoot(ElementName = "FooData", Namespace="http://foo.bar")]
public abstract partial class AbstractFoo
{
    // Some abstract props etc.
}

具體類示例:

public partial class ConcreteFooOne : AbstractFoo
{
    // Some properties, constructor etc.
}

XML根示例:

<FooData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteFooOne" RequestResponse="Request" xmlns="http://foo.bar">

僅包含XML root作為示例,因為這似乎是問題所在。 現在我可以序列化很好,但是在反序列化中,如果我通過傳入抽象類型反序列化,我當然會得到一個異常,說明類型“AbstractFoo”是抽象的。 所以我只是改變了邏輯,以便將具體類型(在這種情況下為ConcreteFooOne)傳遞給序列化器。 現在我得到一個“http://foo.bar'>沒有預料到”。 我假設這是因為序列化程序不知道根節點應該是什么?

我在抽象類上定義了根節點,因為這對於所有具體實現都是相同的。 具體類型由“RequestResponse”屬性定義(或者如果存在,則xsi:type屬性也可以工作,因為它給出了實際的類型名稱)。 有沒有辦法讓序列化程序獲取抽象類所需的內容,或者我對此完全采用錯誤的方法?

  • 請注意,我不能過多地更改類結構,因為它非常基於第三方提供的某些XML模式。

在此先感謝任何人的幫助,我們將不勝感激。

將[XmlRoot(ElementName =“FooData”,Namespace =“ http://foo.bar ”)]添加到子類

這是我做的一個例子:

  [XmlIncludeAttribute(typeof(ConcreteFooOne))]
  [XmlIncludeAttribute(typeof(ConcreteFooTwo))]
  [XmlIncludeAttribute(typeof(ConcreteFooThree))]
  [XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
  public abstract partial class AbstractFoo
  {
    // Some abstract props etc.
  }

  [XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
  public class ConcreteFooOne : AbstractFoo
  {
    public int MyProp { get; set; }
  }
  [XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
  public class ConcreteFooTwo : AbstractFoo
  {

  }
  [XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")]
  public class ConcreteFooThree : AbstractFoo
  {

  }

  class Program
  {
    static void Main(string[] args)
    {
      var serializer = new System.Xml.Serialization.XmlSerializer(typeof(AbstractFoo));
      using (var stream = new FileStream("test.txt", FileMode.OpenOrCreate))
      {
        serializer.Serialize(stream, new ConcreteFooOne() { MyProp = 10 });
        stream.Flush();
      }


      using (var stream = new FileStream("test.txt", FileMode.OpenOrCreate))
      {
        var c = serializer.Deserialize(stream);
      }
    }
  }

這很簡單,在客戶端實現deserealize時,定義一個XmlSerializer如:

XmlSerializer xs= new XmlSerializer (typeof (AbstractFoo),
                  new Type[] { typeof (ConcreteFooOne), typeof (ConcreteFooTwo) } );

然后你可以嘗試:

//it instantiate the correct class, need a streamreader
var myclass = xs.Deserialize(reader);

if (myclass is ConcreteFooOne)
//do something

if (myclass is ConcreteFooTwo)
//do something

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM