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
в качестве одного из его параметров?
Ответы
Ответ 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;
}