簡體   English   中英

如何使用XmlSerializer序列化Object類型的屬性

[英]How to serialize property of type Object with XmlSerializer

我有一個屬性:

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 / <?xml>等)是:

<Test>
  <b>abc</b>
</Test>

<Test>
  <a>123</a>
</Test>

<Test>
  <c>456.7</c>
</Test>

我做了它實現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; }
}

這樣,您可以在所有情況下保留元素名稱<Tag>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM