如果我有类似的东西:
public abstract class Animal { }
[XmlRoot]
public class Dog:Animal { }
[XmlRoot]
Public class Cat:Animal { }
我该如何序列化(然后能够反序列化)一个Cat对象,比如:
<Cat> </Cat>
而不是像
<Animal type="Cat"> </Animal>
我试过使用系统中的不同组合。Xml。序列化和系统。运行时。序列化名称空间,但我似乎无法获得它。
通过在序列化程序中指定对象的类型,我可以使序列化的对象看起来像我想要的样子。这适用于序列化,但不适用于反序列化。。因为我不知道xml中对象的类型。
一个可能的解决方案是:
public abstract class Animal
{
static Dictionary<String,Type> typeDic;
static Animal()
{
typeDic = new Dictionary<string, Type>();
//Get classes in the same namespace of this object
Type ctype = typeof(Animal);
Type[] types = ctype.Assembly.GetTypes().Where(t => String.Equals(t.Namespace, ctype.Namespace, StringComparison.Ordinal)).ToArray();
//For any XmlRootAttribute objects, add the ElementName and Type to a dictionary
foreach(Type type in types)
{
foreach (XmlRootAttribute xmlRoot in type.GetCustomAttributes(typeof(XmlRootAttribute), false))
{
typeDic.Add(xmlRoot.ElementName, type);
}
}
}
public static Content read(String XML)
{
XmlSerializer s = null;
//check the first element to see what the name is, then create the serializer using the type from the dictionary
XmlReader reader = XmlReader.Create(GenerateStreamFromString(XML));
reader.Read();
if (reader.Name == "xml")
{
while (reader.MoveToContent() != XmlNodeType.Element) { }
}
if (typeDic.ContainsKey(reader.Name))
s = new XmlSerializer(typeDic[reader.Name]);
else
throw new Exception("Unknown Type in read");
return (Content)s.Deserialize(reader);
}
public static string write<T>(T f)
{
XmlSerializer s = new XmlSerializer(typeof(T));
MemoryStream stream = new MemoryStream();
s.Serialize(stream, f);
stream.Position = 0;
return StreamToString(stream);
}
}
[XmlRoot(ElementName="Dog")]
public class Dog:Animal { }
[XmlRoot(ElementName="Cat")]
Public class Cat:Animal { }
我试了很长时间,也没能弄清楚。我唯一能想到的就是使用一些反射并自己生成文档:
class Program
{
static void Main(string[] args)
{
List<Animal> animals = new List<Animal>
{
new Dog{Name = "Ernie", HasFleas = true},
new Cat{ Name = "Bert", Collar = "Blue with a little bell" }
};
XDocument doc = new XDocument();
doc.Declaration = new XDeclaration("1.0","utf-8","true");
doc.Add(new XElement("root", animals.Select(animal => animal.GetElement)));
Console.WriteLine(doc);
}
}
public abstract class Animal
{
[XmlAttribute]
public string Name { get; set; }
public XElement GetElement
{
get
{
Type type = this.GetType();
XElement result = new XElement(type.Name);
foreach (PropertyInfo property in
type.GetProperties().Where(pi=> pi.CustomAttributes.Any(ca=> ca.AttributeType == typeof(System.Xml.Serialization.XmlAttributeAttribute))))
{
result.Add(new XAttribute(property.Name,property.GetValue(this)));
}
foreach (PropertyInfo property in
type.GetProperties().Where(pi => pi.CustomAttributes.Any(ca => ca.AttributeType == typeof(System.Xml.Serialization.XmlElementAttribute))))
{
result.Add(new XElement(property.Name,property.GetValue(this)));
}
return result;
}
}
}
public class Dog : Animal
{
[XmlAttribute]
public bool HasFleas { get; set; }
}
public class Cat : Animal
{
[XmlElement]
public string Collar { get; set; }
}
要反序列化,您必须以另一种方式进行,因此需要某种形式的工厂。