Reputation: 154
I'm making a hotel app as a school project and I can't seem to get this working. I have an abstract class Arrangementen and 3 derived classes.
FamilieArrangementen : StandaardArrangementen StandaardArrangementen : Arrangementen LuxeArrangementen : Arrangementen
Every time i Deserialize the XML file i get the exception System.InvalidOperationException < StandaardArrangement xmlns=" /> was not expected.
I have searched the web for an answer and I'm guessig it is something with the XmlRoot namespace or the XmlInclude is not working correctly
Any suggestions?
This is my code
abstract class Arrangementen
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
{
...
}
}
Serialization code
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);
}
}
Deserialization code
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;
}
the other attempt (which not worked, but gave another error
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;
}
the Xml file with a StandaardArrangement
<?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>
Upvotes: 2
Views: 2285
Reputation: 1425
I'm seeing that you're using ".GetType" to resolve the specific type when you Serialize, but you force the parent type, Arrangement, to DeSerialize. (as someone else also just posted :) )
That is causing the error. Just like Serializing, you have to have the explicit type available; it isn't going to try every child automatically for Deserialize.
An easy answer is to query the xml string for the name.
Before loading the XmlSerializer, load an XmlDocument.
Grab that root name from XmlDocument.DocumentElement.Name.
Use the static Type.GetType method on the string name for the XmlSerializer type.
http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.documentelement(v=vs.110).aspx
Type.GetType("namespace.a.b.ClassName") returns null
Upvotes: 2
Reputation: 14982
Right, a few things are tricky here. First of all, you are trying to read a specific type from XML (StandaardArrangement
) while your XmlSerializer
is of its base type Arrangement
. That is what is causing the exception you see. The XmlSerializer
is expecting to read an Arrangement
type, while it encounters a StandaardArrangement
.
If you would change your reader to
var xmls = new XmlSerializer(typeof(StandaardArrangement));
then this specific part of XML you posted would be deserialized to your desired object of StandaardArrangement
.
I am guessing that is also no solution for you, because you probably have a bunch of Arrangement
objects stored in XML, which are mixed in one XML file (I guess?).
What I would suggest is a class that contains a Collection
of Arrangement
objects which you read from XML.
That would result in something like this... (left out specifics, you'll get the idea)
The container class:
public class Arrangements
{
[XmlArray("Arrangement")]
[XmlArrayItem("StandaardArrangement", typeof(StandaardArrangement)]
[XmlArrayItem("LuxeArrangement", typeof(LuxeArrangement)]
public List<Arrangement> Arrangements
{
...
}
}
Again, I left out a lot of specifics, I assume you can fill in the blanks.
HTH!
The XML (left out details just to give an idea, you probably understand what I mean already anyway):
Upvotes: 0