XmlSerializer:“类型'类型'可能不会在此上下文中使用”

时间:2010-10-09 20:45:07

标签: c# xml-serialization

我正试图弄清楚如何使用 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 (和派生类型),直到在派生层次结构中引入泛型类。额外类型的序列化器应涵盖所有预期类型。
  • 如果是基于 ReactObject 泛型类派生的类型,则无法使用 ReactObject 类型的序列化程序序列化该类型,但是使用了通用类型的序列化器。

这可能是一个问题,因为当我需要反序列化时,我必须知道序列化对象的类型。相反,反序列化“非泛型” ReactObject 类型足以使用 ReactObject 类型的公共序列化程序,而不知道序列化对象的确切类型。

(*)实际上我不知道这个目标会带来明显的改善。核心问题是“所有(包含)类型的单个序列化程序集合或每种类型的序列化程序集合更好吗?

3 个答案:

答案 0 :(得分:0)

ReactListObject是否继承自ReactObjectser1被实例化以序列化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;
}