使用派生类将抽象类序列化为XML。 System.InvalidOperationException<类xmlns =“/>未被预期

时间:2013-12-28 11:09:45

标签: c# xml-serialization abstract-class derived-class

我正在将酒店应用作为一个学校项目,我似乎无法让这个工作。 我有一个抽象类Arrangementen和3个派生类。

FamilieArrangementen:StandaardArrangementen StandaardArrangementen:安排 LuxeArrangementen:Arrangementen

每次反序列化XML文件时都会出现异常 System.InvalidOperationException< StandaardArrangement xmlns =“/>不是预期的。

我在网上搜索了一个答案,我猜它是 XmlRoot命名空间 XmlInclude 无法正常工作

有什么建议吗?

这是我的代码

抽象类安排

namespace HotelLib.Overkoepelend.Arrangementen
{
    [Serializable()]
    [XmlInclude(typeof(FamilieArrangement))]
    [XmlInclude(typeof(StandaardArrangement))]
    [XmlInclude(typeof(LuxeArrangement))]
    public abstract class Arrangement: ICloneable
    {
    ...
    }
}

class FamilieArrangement

namespace HotelLib.Overkoepelend.Arrangementen
{
    [Serializable]
    public class FamilieArrangement : StandaardArrangement
    {
    ...
    }
}

class StandaardArrangement

namespace HotelLib.Overkoepelend.Arrangementen
{
    [Serializable]
    public class StandaardArrangement : Arrangement
    {
    ...
    }
}

class LuxeArrangement

namespace HotelLib.Overkoepelend.Arrangementen
{
    [Serializable]
    public class LuxeArrangement : Arrangement
    {
    ...
    }
}

序列化代码

internal void WriteArrangement(Arrangement ar, string path)
{
    using (FileStream bestand = File.Open(path, FileMode.OpenOrCreate))
    {         
        XmlSerializer xmls = new XmlSerializer(ar.GetType());
        xmls.Serialize(bestand, ar);
    }
}

反序列化代码

internal Arrangement ReadArrangement(string path)
{
    if (File.Exists(path))
    {
        using (FileStream bestand = File.Open(path, FileMode.OpenOrCreate))
        {    
            try
            {
                xmls = new XmlSerializer(typeof(Arrangement));
                Arrangement ar = (Arrangement) xmls.Deserialize(bestand);
                bestand.Close();
                return ar;
            }
            catch (Exception er)
            {
                MessageBox.Show("" + er.GetBaseException());
            } 
            bestand.Close();       
        }
    }
    return null;
}

另一次尝试(没有奏效,但又出现了另一个错误

internal Arrangement ReadArrangement(string pad)
        {
            if (File.Exists(pad))
            {
                using (FileStream bestand = File.Open(pad, FileMode.OpenOrCreate))
                {    
                    try
                    {
                        xmls = new XmlSerializer(typeof(Arrangement));
                        Arrangement ar = (Arrangement) xmls.Deserialize(bestand);

                        bestand.Close();
                        return ar;
                    }
                    catch (Exception )
                    {
                        try
                        {
                            xmls = new XmlSerializer(typeof(FamilieArrangement));
                            FamilieArrangement ar = (FamilieArrangement)xmls.Deserialize(bestand);

                            bestand.Close();
                            return ar;
                        }
                        catch (Exception)
                        {
                            try
                            {
                                xmls = new XmlSerializer(typeof(StandaardArrangement));
                                StandaardArrangement ar = (StandaardArrangement)xmls.Deserialize(bestand);

                                bestand.Close();
                                return ar;
                            }
                            catch (Exception er)
                            {
                                MessageBox.Show("" + er.GetBaseException());
                            } 
                        } 
                    } 

                    bestand.Close();       
                }
            }

            return null;
        }

带有StandaardArrangement

的Xml文件
<?xml version="1.0"?>
<StandaardArrangement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <AantalVolw xmlns="HotelLib.Overkoepelend.Arrangementen">2</AantalVolw>
  <Kamer xmlns="HotelLib.Overkoepelend.Arrangementen">
    <MaxAantal>4</MaxAantal>
    <Bezetting>
      <Tijdslot>
        <Aankomst>2013-12-28T10:18:21.4384129+01:00</Aankomst>
        <Vertrek>2013-12-31T10:18:21</Vertrek>
      </Tijdslot>
    </Bezetting>
  </Kamer>
  <KlantId xmlns="HotelLib.Overkoepelend.Arrangementen">d4d72906-7b04-46aa-9986-4f22b232fbd0</KlantId>
  <Tijdslot xmlns="HotelLib.Overkoepelend.Arrangementen">
    <Aankomst>2013-12-28T15:09:10.1152899+01:00</Aankomst>
    <Vertrek>2013-12-30T15:09:10.1152899+01:00</Vertrek>
  </Tijdslot>
  <Type xmlns="HotelLib.Overkoepelend.Arrangementen">standaard</Type>
  <MaaltijdType>halfpension</MaaltijdType>
  <Opties>
    <KamerOpties>kluis</KamerOpties>
    <KamerOpties>wifi</KamerOpties>
  </Opties>
</StandaardArrangement>

2 个答案:

答案 0 :(得分:2)

我看到您在序列化时使用“.GetType”来解析特定类型,但是您强制将父类型Arrangement设置为DeSerialize。 (正如其他人也刚刚发布:))

这导致了错误。就像序列化一样,你必须有明确的类型;它不会自动为每个孩子进行反序列化。

一个简单的答案是查询xml字符串中的名称。

在加载XmlSerializer之前,请加载XmlDocument。

从中获取根名称 XmlDocument.DocumentElement.Name。

对XmlSerializer类型的字符串名称使用静态Type.GetType方法。

http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.documentelement(v=vs.110).aspx

Type.GetType("namespace.a.b.ClassName") returns null

答案 1 :(得分:0)

对,这里有些事情很棘手。首先,您尝试从XML(StandaardArrangement)读取特定类型,而XmlSerializer的基本类型为Arrangement。这就是导致您看到的异常的原因。 XmlSerializer期待阅读Arrangement类型,同时遇到StandaardArrangement

如果您要将读者更改为

var xmls = new XmlSerializer(typeof(StandaardArrangement));

然后,您发布的XML的这一特定部分将被反序列化为您想要的StandaardArrangement对象。

我猜这也不适合你,因为你可能有一堆Arrangement个对象存储在XML中,这些对象混合在一个XML文件中(我猜?)。

我建议的是一个包含Collection Arrangementpublic class Arrangements { [XmlArray("Arrangement")] [XmlArrayItem("StandaardArrangement", typeof(StandaardArrangement)] [XmlArrayItem("LuxeArrangement", typeof(LuxeArrangement)] public List<Arrangement> Arrangements { ... } } 个对象的类,您可以从XML中读取这些对象。

这会导致类似这样的事情......(遗漏了细节,你会得到这个想法)

容器类:

{{1}}

同样,我遗漏了很多细节,我认为你可以填补空白。

HTH!

XML(遗漏了细节只是为了给出一个想法,你可能已经理解我的意思了):