Reputation: 31
I'm trying to deserialize some xml files into some classes which have been simplified to the following:
[XmlRoot("person")]
[Serializable]
public class Person
{
[XmlElement]
public Toy Toy { get; set; }
}
[Serializable]
public class ActionMan : Toy
{
[XmlElement("guns")]
public string Guns;
}
[Serializable]
public class Doll : Toy
{
[XmlElement("name")]
public String Name;
}
[XmlInclude(typeof(Doll))]
[XmlInclude(typeof(ActionMan))]
public class Toy
{
}
[TestFixture]
public class ToyTest
{
[Test]
public void testHierarchy()
{
String filePath = @"test\brother.xml";
String sisfilePath = @"test\sister.xml";
var serializer = new XmlSerializer(typeof(Person));
Person brother = (Person)serializer.Deserialize(new FileStream(filePath, FileMode.Open));
Person sister = (Person)serializer.Deserialize(new FileStream(sisfilePath, FileMode.Open));
Assert.IsNotNull(brother);
Assert.IsNotNull(sister);
Assert.IsAssignableFrom(typeof(ActionMan),brother.Toy);
Assert.IsAssignableFrom(typeof(Doll),sister.Toy);
}
}
I want to use the c# Serialisation (I know I can use my own deserialiser) and I think I'm perhaps simply missing a particular tag that I don't know about (and I'm sure I've got superfluous tags).
here is one fo the xml files:
<person>
<doll>
<name>Jill</name>
</doll>
</person>
the error I get is "Expected: assignable from " on the third assert
Upvotes: 3
Views: 1314
Reputation: 8772
Try the following
public class Person
{
public Toy toy
{
get
{
return (doll == null) ? (Toy)actionMan : (Toy)doll;
}
}
public Doll doll;
public ActionMan actionMan;
}
public class Toy
{
}
public class Doll : Toy
{
public String name;
}
public class ActionMan : Toy
{
public String guns;
}
class Program
{
static void Main(string[] args)
{
Person brother = new Person();
ActionMan am = new ActionMan();
am.guns = "Laser Beam";
brother.actionMan = am;
Person sister = new Person();
Doll d = new Doll();
d.name = "Jill";
sister.doll = d;
Serialize(brother, "brother.xml");
Serialize(sister, "sister.xml");
Person b = Deserialize("brother.xml");
Person s = Deserialize("sister.xml");
Console.WriteLine(((ActionMan)b.toy).guns);
Console.WriteLine(((Doll)s.toy).name);
Console.Read();
}
public static Person Deserialize(String filename)
{
var serializer = new XmlSerializer(typeof(Person));
return (Person)serializer.Deserialize(new FileStream(filename, FileMode.Open));
}
public static void Serialize(Person p, String filename){
Stream stream = File.Open(filename, FileMode.Create);
XmlSerializer s = new XmlSerializer(typeof(Person));
s.Serialize(stream, p);
stream.Close();
}
You can expand from here. Remember that, in the attribute names, casing matters. The serialization output I got is
brother.xml
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<actionMan>
<guns>Laser Beam</guns>
</actionMan>
</Person>
sister.xml
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<doll>
<name>Jill</name>
</doll>
</Person>
The output is
Laser Beam
Jill
Upvotes: 0
Reputation: 29264
What I have done, is designed the class structure the way I want, fill in some basic data and then serialize it. Then examine how it serializes and adjust the Xml attributes. If your Toy
class has only a few derivatives, then you can de-serialize them seperately with a action-man field and a doll field that might be null or not.
Alternatively to go from an Xml file to a c# class I use the xsd.exe
tool to generate a .xsd
file with xsd mydata.xml
and then from that a c# class file with xsd /c /l:cs mydata.xsd
. Then I examine the class data to get clues as to how to define my class and what attributes to use.
link to xsd tool from Microsoft.
Upvotes: 1
Reputation: 12849
When I try to serialize your structure (person, who has ActionMan as Toy) i get
<person> <Toy xsi:type="ActionMan" /> </person>
I guess this is how you can handle inheritance of your types. But I guess you cant change your already serialised XML.
Upvotes: 1
Reputation: 8772
Class person should contain a "doll" attribute instead of a "Toy" attribute, I mean the name. The XML node must have the same name as the attribute name -casing matters.
Upvotes: 1