XmlSerializer ne sérialisera pas IEnumerable
j'ai un enregistreur d'invocation qui est destiné à enregistrer tous les appels de méthode avec les paramètres associés à la méthode utilisant XmlSerializer. Il fonctionne bien pour la plupart des appels, mais il déclenche une exception pour toutes les méthodes qui a un paramètre de IEnumerable
type.
Par exemple, void MethodWithPlace( Place value )
serait sérialisé, mais void MethodWithPlace( IEnumerable<Place> value )
ne le serait pas.
L'exception est
Système.NotSupportedException: impossible de sérialiser l'interface Système.Collection.Générique.IEnumerable`1[[Place, Test, Version = 0.0.0.0, Culture = neutre]]].
Que dois-je faire pour que cela fonctionne avec ces méthodes avec IEnumerable
comme l'un de ses paramètres?
7 réponses
la façon dont vous sérialisez une propriété IEnumerable est avec une propriété de substitution
[XmlRoot]
public class Entity {
[XmlIgnore]
public IEnumerable<Foo> Foo { get; set; }
[XmlElement, Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public List<Foo> FooSurrogate { get { return Foo.ToList(); } set { Foo = value; } }
}
C'est moche, mais il fait le travail. La meilleure solution est d'écrire une classe de substitution (i.e. EntitySurrogate).
fondamentalement un XmlSerializer ne peut pas sérialiser une interface. La solution est donc de lui donner une instance concrète à sérialiser. Selon le fonctionnement de votre Logger d'invocation, j'envisagerais d'utiliser
var serializer = new XmlSerializer(value.GetType());
je ne pense pas que vous serez en mesure de sérialiser. Essayez de convertir le IEnumerable à une liste et alors vous serez en mesure de sérialiser.
pour être sérialisable XML, les types qui héritent de IEnumerable doivent avoir une implémentation de Add (System.Objet) à tous les niveaux de leur hiérarchie d'héritage. {votre classe} ne pas mettre en œuvre Add(Système d'.Objet.)
implémentez la fonction Add (), vous pourriez résoudre le problème
peut-être pas la meilleure façon, mais ça a marché pour moi. J'ai créé une méthode de sérialisation.
Utiliser
var xml = Util.ObjetoToXML (obj, null, null).OuterXml;
méthode
public static XmlDocument ObjetoToXML(object obj, XmlDocument xmlDocument, XmlNode rootNode)
{
if (xmlDocument == null)
xmlDocument = new XmlDocument();
if (obj == null) return xmlDocument;
Type type = obj.GetType();
if (rootNode == null) {
rootNode = xmlDocument.CreateElement(string.Empty, type.Name, string.Empty);
xmlDocument.AppendChild(rootNode);
}
if (type.IsPrimitive || type == typeof(Decimal) || type == typeof(String) || type == typeof(DateTime))
{
// Simples types
if (obj != null)
rootNode.InnerText = obj.ToString();
}
else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
// Genericis types
XmlNode node = null;
foreach (var item in (IEnumerable)obj)
{
if (node == null)
{
node = xmlDocument.CreateElement(string.Empty, item.GetType().Name, string.Empty);
node = rootNode.AppendChild(node);
}
ObjetoToXML(item, xmlDocument, node);
}
}
else
{
// Classes types
foreach (var propertie in obj.GetType().GetProperties())
{
XmlNode node = xmlDocument.CreateElement(string.Empty, propertie.Name, string.Empty);
node = rootNode.AppendChild(node);
var valor = propertie.GetValue(obj, null);
ObjetoToXML(valor, xmlDocument, node);
}
}
return xmlDocument;
}
XmlSerializer ne supporte pas cela. Essayez YAXLib pour ces types de sérialisations.
Vous pouvez utiliser DataContractSerializer
using (var ms = new MemoryStream())
{
var serialiser = new DataContractSerializer(typeof (EnvironmentMetadata));
serialiser.WriteObject(ms, environmentMetadata);
var s = Encoding.ASCII.GetString(ms.ToArray());
return s;
}