5

我有一个带有几个具体实现的抽象类。这需要序列化为 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 根作为示例,因为这似乎是问题所在。现在我可以很好地序列化,但是在反序列化时,如果我通过传入抽象类型来反序列化,我当然会得到一个异常,说明类型“AbstractFoo”是抽象的。所以我只是更改了逻辑,而是将具体类型(在本例中为 ConcreteFooOne)传递给序列化程序。现在我得到一个“http://foo.bar'> 不是预期的”。我假设这是因为序列化程序不知道根节点应该是什么?

我在抽象类上定义了根节点,因为这对于所有具体实现都是相同的。具体类型由“RequestResponse”属性定义(或者 xsi:type 属性如果存在也可以工作,因为它为我们提供了实际的类型名称)。有没有办法让序列化程序从抽象类中获取所需的内容,或者我是否完全错误地这样做了?

  • 请注意,我不能过多地更改类结构,因为它非常接近第 3 方提供的一些 XML 模式。

提前感谢任何人对此的帮助,将不胜感激。

4

2 回答 2

5

将 [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);
      }
    }
  }
于 2013-07-19T10:48:39.413 回答
1

很简单,在客户端中当你去实现时,定义一个XmlSerializerlike:

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
于 2013-10-31T03:54:02.773 回答