我有一個屬性:如何序列類型對象的屬性與XmlSerializer的
public object Tag
但它可以包含有限數量的類型,不幸的是無鹼基類型(除對象類型)。但是當我用這個屬性序列化對象時,它不會被序列化。有沒有辦法指示XmlSerializer可能的類型?
我有一個屬性:如何序列類型對象的屬性與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>
完美的作品! – user919426 2015-03-23 09:36:44
只有對元素使用不同的名稱或名稱空間時,這纔有效(本例中爲a,b,c)。就我而言,我需要元素名稱始終相同,所以我發佈了一個似乎適用於我的答案。 – Evan 2017-04-07 20:08:34
我做到了實現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
您還可以在的類,它包含的對象屬性使用[XmlInclude(typeof(YourType))]
。因此,在OP的情況下,它看起來像這樣
[XmlInclude(typeof(PossibleClassOne))]
[XmlInclude(typeof(PossibleClassTwo))]
public class MyClass
{
public object Tag { get; set; }
}
這樣,您就可以保持你的元素名稱<Tag>
在所有情況下
我期望你可以實現了ISerializable和控制的序列化對象取決於標籤的類型,將其轉換爲可序列化的類型。但是我不知道你以後如何反序列化對象。序列化對象類型的東西可能不是一個好主意。 – 2012-02-29 10:31:15
@Adrian'XmlSerializer'不關心'ISerializable';然而,我同意坦率地說,這種情況最好簡單地避免 – 2012-02-29 10:33:05
@Marc XmlSerializer並不關心ISerialiable,但它確實關心IXmlSerializable,並且會在實現它的對象上調用讀寫方法。 – Fen 2012-02-29 11:18:07