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?

32
demandé sur John Saunders 2012-02-01 23:47:45

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).

26
répondu Herman Schoenfeld 2017-07-25 11:15:02

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());
9
répondu Kyle W 2012-02-01 19:52:07

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.

8
répondu Chris 2012-02-01 21:47:05

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

3
répondu what is sleep 2013-09-20 21:47:43

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;

    }
0
répondu Everson Rafael 2016-05-02 17:13:59

XmlSerializer ne supporte pas cela. Essayez YAXLib pour ces types de sérialisations.

-1
répondu Sina Iravanian 2012-02-14 15:47:52

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;
        }
-1
répondu Maxim Eliseev 2015-01-14 15:37:17