Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从XML反序列化抽象类的具体实现_C#_.net_Xml_Serialization_Abstract - Fatal编程技术网

C# 如何从XML反序列化抽象类的具体实现

C# 如何从XML反序列化抽象类的具体实现,c#,.net,xml,serialization,abstract,C#,.net,Xml,Serialization,Abstract,我有一个抽象类,有几个具体的实现。这需要序列化为XML以便发送到另一个系统-这工作正常。但是,我还需要能够反序列化相同的XML结构。不管我怎么做,我似乎都做不到。我的班级结构如下: 抽象类: [XmlIncludeAttribute(typeof(ConcreteFooOne))] [XmlIncludeAttribute(typeof(ConcreteFooTwo))] [XmlIncludeAttribute(typeof(ConcreteFooThree))] [XmlRoot(Eleme

我有一个抽象类,有几个具体的实现。这需要序列化为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.
}
<FooData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteFooOne" RequestResponse="Request" xmlns="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.
}
public partial class ConcreteFooOne : AbstractFoo
{
    // Some properties, constructor etc.
}
<FooData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteFooOne" RequestResponse="Request" xmlns="http://foo.bar">
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.
}
<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属性也可以工作,如果它提供了实际的类型名称)。有没有一种方法可以让序列化程序从抽象类中提取所需的内容,或者我在这方面完全走错了方向

  • 请注意,我不能对类结构进行太多更改,因为它非常接近于第三方提供的一些XML模式
在此提前感谢任何人的帮助,我们将不胜感激。

将[XmlRoot(ElementName=“FooData”,Namespace=”“)添加到子类中

下面是我举的一个例子:

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

很简单,在客户端反序列化时,定义一个
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

我刚刚知道这会有用的,谢谢。如果我可以只在抽象类上定义“XmlRoot”属性就好了,因为不管有什么实现,它都是相同的。您知道实现这一点的方法吗,还是我必须在任何具体的类中不断复制“XmlRoot”?不,您不能只在基类中这样做,您可以检查属性的内在性问题