标签:
http://coding-time.blogspot.hk/2008/03/serialize-object-graph-to-xml-in-net.html
How to serialize any data structure to XML? My first idea was XmlSerializer. But then I found out it had some serious drawbacks. Luckily, there is a better option - NetDataContractSerializer.
In .Net, there are a few classes for (de)serialization. This is an overview of their features:
XmlSerializer
DataContractSerializer
NetDataContractSerializer - better!
BinarryFormatter
SoapFormatter
- All serializers need the type to be serialized marked by SerializableAttribute.
What does it mean that XmlSerializer has to know all types that could be encountered during serialization in advance?
Imagine that we have two classes: Base and Derived.
[Serializable]
public class Base
{
public string name;
public Base()
{
name = "base instance";
}
}
[Serializable]
public class Derived : Base
{
public Derived left;
public Derived right;
public Derived()
{
}
}
What if we have a reference to Base and we actually don‘t want to care about the actual type?
Base b = new Derived();
// we only know we are holding reference to Base
// and we don‘t want to care about the actual type
XmlSerializer ser = new XmlSerializer(typeof(Base));
// serialize
using (FileStream fs = File.Create(AppDomain.CurrentDomain.BaseDirectory + "data.xml"))
{
// XmlSerializer throws an Exception
ser.Serialize(fs, b);
}
// deserialize
using (FileStream fs = File.OpenRead(AppDomain.CurrentDomain.BaseDirectory + "data.xml"))
{
Base baseDeserialized = (Base)ser.Deserialize(fs);Derived deserialize = baseDeserialized as Derived;
}
XmlSerializer
throws an exception, because it encounters an "unknown" type - Derived.
We could solve this by passing all the possible derived types in
constructor of XmlSerializer or tagging all by XmlIncludeAttribute. This
is of course inconvenient if you have a lot of classes. The worst thing
is that when you add a derived class, you have to change code
elsewhere.
NetDataContractSerializer doesn‘t have this problem.
The
second issue with XmlSerializer is that it cannot serialize complex
object graph. What does it mean "to serialize object graph"?
Derived top = new Derived();
top.left = new Derived();
top.left.name = "left son";
top.right = new Derived();
top.right.name = "right son";
top.left.right = new Derived();
// top
// / \
// left right
// \ /
// bottom
top.right.left = top.left.right;
XmlSerializer ser = new XmlSerializer(typeof(Derived));
using (FileStream fs = File.Create(AppDomain.CurrentDomain.BaseDirectory + "data.xml"))
{
ser.Serialize(fs, top);
}
using (FileStream fs = File.OpenRead(AppDomain.CurrentDomain.BaseDirectory + "data.xml"))
{
Derived deserialized = (Derived)ser.Deserialize(fs);
// false - we want true
bool ok = deserialized.left.right == deserialized.right.left;
}
After deserialization, deserialized.left.right
== deserialized.right.left is false, that means the object graph is
different. Worse - XmlSerializer cannot serialize circular references at
all.
Again, NetDataContractSerializer doesn‘t have any of these problems.
Serialize object graph to XML in .Net
标签:
原文地址:http://www.cnblogs.com/lilei9110/p/4746017.html