Я пытаюсь выяснить, как сериализовать любой класс с помощью XmlSerializer, не используя атрибут XmlInclude. Обычно работает, но со следующим кодом я получаю исключение:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
namespace Test
{
public class ReactObject { }
public class ReactListObject : ReactObject { }
public class ReactList<T> : ReactObject, ICollection, IList<T>
{
public ReactList() { }
public virtual void AddRange(IEnumerable<T> values) { }
[XmlArray(ElementName = "Items", IsNullable = false)]
public T[] Items
{
get { lock (SyncRoot) { return (ItemsList.ToArray()); } }
set { lock (SyncRoot) { ItemsList = new List<T>(value); } }
}
protected List<T> ItemsList = new List<T>();
public bool IsSynchronized { get { return (true); } }
public object SyncRoot { get { return (mRootObject); } }
private object mRootObject = new object();
public void CopyTo(Array array, int index) { CopyTo(array, index); }
[XmlIgnore()]
public T this[int index] {
get { return (ItemsList[index]); }
set { ItemsList[index] = value; }
}
public int IndexOf(T item) { return (ItemsList.IndexOf(item)); }
public virtual void Insert(int index, T item) { }
public virtual void RemoveAt(int index) { }
public int Count { get { lock (SyncRoot) { return (ItemsList.Count); } } }
public bool IsReadOnly { get { return (false); } }
public virtual void Add(T item) { ItemsList.Add(item); }
public void Clear() { }
public bool Contains(T item) { return (false); }
public virtual void CopyTo(T[] array, int arrayIndex) { }
public virtual bool Remove(T item) { return (false); }
public IEnumerator<T> GetEnumerator() { return (ItemsList.GetEnumerator()); }
IEnumerator IEnumerable.GetEnumerator() { return (ItemsList.GetEnumerator()); }
}
[XmlInclude(typeof(B))]
public class A : ReactListObject
{
public int AValue = 1;
}
public class B : A
{
public int BValue = 2;
}
public class AList : ReactList<A>
{
}
static class Program
{
[STAThread]
static void Main()
{
// NOT good serializer for the type AList
XmlSerializer ser1 = new XmlSerializer(typeof(ReactObject), new Type[] { typeof(A), typeof(B), typeof(ReactList<A>), typeof(AList) });
// Good serializer for the type AList
XmlSerializer ser2 = new XmlSerializer(typeof(ReactList<A>), new Type[] { typeof(A), typeof(B), typeof(AList) });
AList list = new AList();
list.Add(new A());
list.Add(new B());
using (FileStream mStream = new FileStream("C:\\Test.xml", FileMode.Create)) {
ser2.Serialize(mStream, list);
}
using (FileStream mStream = new FileStream("C:\\Test.xml", FileMode.Create)) {
ser1.Serialize(mStream, list);
}
}
}
}
Вызов исключения
Тип Test.AList не может использоваться в этом контексте
Вот диаграмма классов, чтобы помочь считывать код
Da DevelopЯ хотел бы рассказать больше о цели, которую я пытаюсь достичь: я хочу свести к минимуму создание экземпляров XML-сериализаторов (на самом деле каждый тип serialized имеет свой собственный сериализатор, приложение будет воссоздавать только существующее сериализатор каждый раз, когда не включенный тип должен быть сериализован. (*)
Кажется, ИМХО,
- Можно сериализовать любые ReactObject (и производные типы) с помощью сериализатора типа ReactObject, пока в иерархии деривации не будет введен общий класс. Дополнительные типы сериализатора должны охватывать все ожидаемые типы.
- В случае типа, полученного из общего класса на основе ReactObject, тип не может быть сериализован с помощью сериализатора типа ReactObject, но с сериализатором родового типа.
Это может быть проблемой, так как я должен знать тип сериализованного объекта, когда мне нужно десериализовать его. Вместо этого для десериализации "неосновного" типа ReactObject достаточно использовать обычный сериализатор типа ReactObject, не зная точного типа сериализованного объекта.
(*) На самом деле я не знаю, что эта цель привела бы к разумным улучшениям. Основной вопрос: ". Лучше ли один сборщик сериализатора для всех (включенных) типов или сборки сериализатора для каждого типа?"