我正试图弄清楚如何使用 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序列化器实例的创建(实际上每个序列化类型都有自己的序列化器;应用程序将重新创建唯一存在的每次不包含类型都应序列化。(*)
看来,恕我直言,
这可能是一个问题,因为当我需要反序列化时,我必须知道序列化对象的类型。相反,反序列化“非泛型” ReactObject 类型足以使用 ReactObject 类型的公共序列化程序,而不知道序列化对象的确切类型。
(*)实际上我不知道这个目标会带来明显的改善。核心问题是“所有(包含)类型的单个序列化程序集合或每种类型的序列化程序集合更好吗?”
答案 0 :(得分:0)
ReactListObject
是否继承自ReactObject
? ser1
被实例化以序列化ReactObject
的类型,但是从您的代码示例中我只能告诉list
类型为ReactListObject
。
答案 1 :(得分:0)
序列化方面很简单 - 在获取序列化程序时不使用typeof(ReactObject),而是使用list.GetType(),它将返回AList而不是ReactObject并创建正确的序列化程序。如果您担心实例化过多的序列化程序,您可以始终将它们保存在按类型键入的字典中。
反序列化更难,因为您必须首先知道对象的类型 - 如果您无法让调用者告诉您期望的类型,则在尝试反序列化以确定类型之前,您需要读取数据。
答案 2 :(得分:-1)
首先不应该是这样的:
//[XmlInclude(typeof(B))]
[Serializable]
public class A : ReactListObject
{
public int AValue = 1;
}
[XmlInclude(typeof(A))]
public class B : A
{
public int BValue = 2;
}