web-dev-qa-db-fra.com

XmlSerializer ne sérialisera pas IEnumerable

J'ai un enregistreur d'invocation qui est destiné à enregistrer tous les appels de méthode ainsi que les paramètres associés à la méthode utilisant XmlSerializer. Cela fonctionne bien pour la plupart des appels, mais il lève une exception pour toutes les méthodes qui ont un paramètre de type IEnumerable.

Par exemple, void MethodWithPlace( Place value ) serait sérialisé, mais void MethodWithPlace( IEnumerable<Place> value ) ne le serait pas.

L'exception est

System.NotSupportedException: impossible de sérialiser l'interface System.Collections.Generic.IEnumerable`1 [[Place, Test, Version = 0.0.0.0, Culture = neutral]].

Que dois-je faire pour le faire fonctionner avec ces méthodes avec IEnumerable comme l'un de ses paramètres?

36
uni

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 ça fait le boulot. La meilleure solution consiste à écrire une classe de substitution (c'est-à-dire EntitySurrogate).

29
Herman Schoenfeld

Fondamentalement, un XmlSerializer ne peut pas sérialiser une interface. La solution est alors de lui donner une instance concrète de sérialisation. Selon la façon dont fonctionne votre enregistreur d'invocation, j'envisagerais d'utiliser

var serializer = new XmlSerializer(value.GetType());
11
Kyle W

Je ne pense pas que vous serez en mesure de sérialiser cela. Essayez de convertir l'IEnumerable en liste et vous pourrez alors sérialiser.

8
Chris

Pour être sérialisables XML, les types qui héritent d'IEnumerable doivent avoir une implémentation de Add (System.Object) à tous les niveaux de leur hiérarchie d'héritage. {votre classe} n'implémente pas Add (System.Object).

implémentez la fonction Add (), vous pourriez résoudre le problème

3
what is sleep

Ce n'est peut-être pas la meilleure façon, mais cela a fonctionné pour moi. J'ai créé une méthode qui fait la sérialisation.

Utilisation

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;

    }
0
Everson Rafael