XmlSerializer не будет сериализовать IEnumerable - PullRequest
35 голосов
/ 01 февраля 2012

У меня есть регистратор вызовов, который предназначен для записи всех вызовов метода вместе с параметрами, связанными с методом с использованием XmlSerializer.Это работает хорошо для большинства вызовов, но выдает исключение для всех методов, которые имеют параметр типа IEnumerable.

Например, void MethodWithPlace( Place value ) будет сериализовано, а void MethodWithPlace( IEnumerable<Place> value ) - нет.

Исключением является

System.NotSupportedException: невозможно сериализовать интерфейс System.Collections.Generic.IEnumerable`1 [[Place, Test, Version = 0.0.0.0, Culture = нейтральный]].

Что мне нужно сделать, чтобы он работал с этими методами с IEnumerable в качестве одного из его параметров?

Ответы [ 7 ]

29 голосов
/ 13 марта 2013

Способ сериализации свойства IEnumerable заключается в суррогатном свойстве

[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; } }
}

Это ужасно, но оно выполняет свою работу.Лучшее решение - написать суррогатный класс (т. Е. EntitySurrogate).

11 голосов
/ 01 февраля 2012

В основном XmlSerializer не может сериализовать интерфейс. Решение, таким образом, состоит в том, чтобы дать ему конкретный экземпляр для сериализации. В зависимости от того, как работает ваш регистратор вызовов, я мог бы рассмотреть возможность использования

var serializer = new XmlSerializer(value.GetType());
8 голосов
/ 01 февраля 2012

Не думаю, что вы сможете сериализовать это.Попробуйте преобразовать IEnumerable в список, и тогда вы сможете сериализоваться.

3 голосов
/ 21 сентября 2013

Чтобы быть сериализуемым в XML, типы, наследуемые от IEnumerable, должны иметь реализацию Add (System.Object) на всех уровнях своей иерархии наследования.{ваш класс} не реализует Add (System.Object).

реализует функцию Add (), вы можете решить проблему

0 голосов
/ 02 мая 2016

Может быть, не лучшим образом, но у меня это сработало. Я создал метод, который делает сериализацию.

Используйте

var xml = Util.ObjetoToXML (obj, null, null) .OuterXml;

метод

        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 голосов
/ 14 января 2015

Вы можете использовать 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;
        }
0 голосов
/ 14 февраля 2012

XmlSerializer не поддерживает это.Попробуйте YAXLib для этих сериализаций.

...