C#自定义Xml序列化

我试图通过XmlSerializer反序列化一个自定义类并遇到一些问题,事实上我不知道我将要反序列化的类型(它是可插入的)并且我很难确定它。

我发现这篇文章看起来很相似,但不能完全使用我的方法,因为我需要反序列化一个XmlSerializable的接口。

我目前得到的是forms。 请注意,我希望并且需要能够处理通过插件实现的A类和B类。 所以,如果我可以避免使用IXmlSerializable(我认为我不能),那就太棒了。

用于A的ReadXml是我坚持的。 但是,如果我可以进行其他改进以改进系统,那么我很乐意这样做。

public class A : IXmlSerializable { public IB MyB { get; set;} public void ReadXml(System.Xml.XmlReader reader) { // deserialize other member attributes SeekElement(reader, "MyB"); string typeName = reader.GetAttribute("Type"); // Somehow need to the type based on the typename. From potentially //an external assembly. Is it possible to use the extra types passed //into an XMlSerializer Constructor??? Type bType = ??? // Somehow then need to deserialize B's Members // Deserialize X // Deserialize Y } public void WriteXml(System.Xml.XmlWriter writer) { // serialize other members as attributes writer.WriteStartElement("MyB"); writer.WriteAttributeString("Type", this.MyB.GetType().ToString()); this.MyB.WriteXml(writer); writer.WriteEndElement(); } private void SeekElement(XmlReader reader, string elementName) { ReaderToNextNode(reader); while (reader.Name != elementName) { ReaderToNextNode(reader); } } private void ReaderToNextNode(XmlReader reader) { reader.Read(); while (reader.NodeType == XmlNodeType.Whitespace) { reader.Read(); } } } public interface IB : IXmlSerializable { } public class B : IB { public void ReadXml(XmlReader reader) { this.X = Convert.ToDouble(reader.GetAttribute("x")); this.Y = Convert.ToDouble(reader.GetAttribute("y")); } public void WriteXml(XmlWriter writer) { writer.WriteAttributeString("x", this.X.ToString()); writer.WriteAttributeString("y", this.Y.ToString()); } } 

注意:更新,因为我意识到B应该使用接口IB。 对不起有点错误的问题。

要从字符串创建实例,请使用Activator.CreateInstance的重载之一。 要获取具有该名称的类型,请使用Type.GetType。

我认为你不需要实现IXmlSerializable ……

由于您在运行时之前不知道实际类型,因此可以动态地将属性覆盖添加到XmlSerializer。 您只需要知道从Ainheritance的类型列表。例如,如果您使用A作为另一个类的属性:

 public class SomeClass { public A SomeProperty { get; set; } } 

您可以为每个派生类型动态地将XmlElementAttribute应用于该属性:

 XmlAttributes attr = new XmlAttributes(); var candidateTypes = from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()) where typeof(A).IsAssignableFrom(t) && !t.IsAbstract select t; foreach(Type t in candidateTypes) { attr.XmlElements.Add(new XmlElementAttribute(t.Name, t)); } XmlAttributeOverrides overrides = new XmlAttributeOverrides(); overrides.Add(typeof(SomeClass), "SomeProperty", attr); XmlSerializer xs = new XmlSerializer(typeof(SomeClass), overrides); ... 

这只是一个非常基本的示例,但它显示了如何在静态运行时在运行时应用XML序列化属性。

我使用xpath快速确定输入xml是否包含A类或B类。然后根据它反序列化它。