如何使用XmlSerializer序列化Object类型的属性

我有一个属性:

public object Tag 

但它可以包含有限数量的类型,遗憾的是没有基类型(对象类型除外)。 但是当我使用此属性序列化对象时,它不会被序列化。 有没有办法用可能的类型指示XmlSerializer?

我不推荐这个,但是,您可以使用[XmlElement]等告诉它有关成员的多个候选类型:

 public class Test { private static void Main() { var ser = new XmlSerializer(typeof (Test)); var obj = new Test {Value = "abc"}; ser.Serialize(Console.Out, obj); obj = new Test { Value = 123 }; ser.Serialize(Console.Out, obj); obj = new Test { Value = 456.7F }; ser.Serialize(Console.Out, obj); } [XmlElement("a", Type = typeof(int))] [XmlElement("b", Type = typeof(string))] [XmlElement("c", Type = typeof(float))] public object Value { get; set; } } 

输出的重要位(忽略所有xmlns / 等)是:

  abc   123   456.7  

我做了它实现IXmlSerializable接口,将对象类型写为元素属性。

  public void ReadXml(XmlReader reader) { reader.MoveToContent(); Boolean isEmptyElement = reader.IsEmptyElement; reader.ReadStartElement(); if (!isEmptyElement) { // ...here comes all other properties deserialization object tag; if (ReadXmlObjectProperty(reader, "Tag", out tag)) { Tag = tag; } reader.ReadEndElement(); } } public void WriteXml(XmlWriter writer) { // ...here comes all other properties serialization WriteXmlObjectProperty(writer, "Tag", Tag); } public static bool ReadXmlObjectProperty(XmlReader reader, string name, out object value) { value = null; // Moves to the element while (!reader.IsStartElement(name)) { return false; } // Get the serialized type string typeName = reader.GetAttribute("Type"); Boolean isEmptyElement = reader.IsEmptyElement; reader.ReadStartElement(); if (!isEmptyElement) { Type type = Type.GetType(typeName); if (type != null) { // Deserialize it XmlSerializer serializer = new XmlSerializer(type); value = serializer.Deserialize(reader); } else { // Type not found within this namespace: get the raw string! string xmlTypeName = typeName.Substring(typeName.LastIndexOf('.')+1); value = reader.ReadElementString(xmlTypeName); } reader.ReadEndElement(); } return true; } public static void WriteXmlObjectProperty(XmlWriter writer, string name, object value) { if (value != null) { Type valueType = value.GetType(); writer.WriteStartElement(name); writer.WriteAttributeString("Type", valueType.FullName); writer.WriteRaw(ToXmlString(value, valueType)); writer.WriteFullEndElement(); } } public static string ToXmlString(object item, Type type) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = Encoding.ASCII; settings.Indent = true; settings.OmitXmlDeclaration = true; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using(StringWriter textWriter = new StringWriter()) using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) { XmlSerializer serializer = new XmlSerializer(type); serializer.Serialize(xmlWriter, item, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty })); return textWriter.ToString(); } } 

注意:在代码中我没有使用命名空间和ASCII编码,这些是非强制性选择。

HTH,Cabbi

您还可以在包含object属性的上使用[XmlInclude(typeof(YourType))] 。 所以在OP的情况下,它看起来像这样

 [XmlInclude(typeof(PossibleClassOne))] [XmlInclude(typeof(PossibleClassTwo))] public class MyClass { public object Tag { get; set; } } 

这样,您可以在所有情况下保留元素名称