ho fatto implementando l'interfaccia IXmlSerializable
, scrivendo il tipo di oggetto come attributo elemento.
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();
}
}
Nota: nel codice non utilizzo spazio dei nomi e codifica ASCII, quelle sono scelte non obbligatorie.
HTH, Cabbi
mi aspetto si potrebbe implementare ISerializable e controllare la serializzazione del oggetto a seconda del tipo di tag, trasmettendolo al suo tipo serializzabile. Tuttavia, non so come deserializzare l'oggetto in un secondo momento. Forse non è una buona idea serializzare le cose di tipo oggetto. –
@Adrian 'XmlSerializer' non si preoccupa di' ISerializable'; tuttavia, sono d'accordo sul fatto che questo scenario è meglio evitare semplicemente –
@Marc XmlSerializer non si preoccupa di ISerialiable, tuttavia si preoccupa di IXmlSerializable e chiamerà i metodi di lettura e scrittura su un oggetto che lo implementa. – Fen