如何从 XML 反序列化抽象类的具体实现 [英] How to deserialize concrete implementation of abstract class from XML

查看:30
本文介绍了如何从 XML 反序列化抽象类的具体实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有几个具体实现的抽象类.这需要序列化为 XML 才能发送到另一个系统 - 这工作正常.但是,我还需要能够反序列化相同的 XML 结构.无论我尝试什么,我似乎都无法做到这一点.我的班级结构如下:

I have an abstract class with a couple of concrete implementations. This needs serializing to XML in order to send to another system - this is working fine. However, I also need to be able to deserialize the same XML structure back. No matter what I try, I don't seem to be able to do this. My class structure is as below:

抽象类:

[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'> 不是预期的".我假设这是因为序列化程序不知道根节点应该是什么?

Only included XML root as example as this appears to be where the issue is. Now I can serialize fine, but on the deserialization, if I deserialize by passing in the abstract type, I of course get an exception stating that type "AbstractFoo" is abstract. So I simply changed the logic so that instead the concrete type (ConcreteFooOne in this case) is passed to the serializer. Now I get a "http://foo.bar'> was not expected". I am presuming that this is because the serializer doesn't know what to root node should be?

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

I have the root node defined on the abstract class as this will be the same for all concrete implementations. The concrete type is defined by the "RequestResponse" attribute (or the xsi:type attribute can work too if it is present as that gives us the actual type name). Is there a way to make the serializer pick up what is required off the abstract class or am I going completely the wrong way about this?

  • 请注意,我不能过多地更改类结构,因为它非常接近于第三方提供的一些 XML 架构.

在此先感谢任何人的帮助,我们将不胜感激.

Thanks in advance for anyone's help with this, it would be much appreciated.

推荐答案

添加 [XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")] 到子类

Add [XmlRoot(ElementName = "FooData", Namespace = "http://foo.bar")] to the sub-classes

这是我做的一个例子:

  [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);
      }
    }
  }

这篇关于如何从 XML 反序列化抽象类的具体实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆