Подтвердить что ты не робот

XmlSerializer не будет сериализовать IEnumerable

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

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

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

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

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

4b9b3361

Ответ 1

Способ сериализации свойства 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).

Ответ 2

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

var serializer = new XmlSerializer(value.GetType());

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

Использование

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;

    }

Ответ 6

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

Ответ 7

Вы можете использовать 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;
        }