C#如何使用XmlSerializer序列化 ArrayList[]

rell336 2015-07-09 10:30:32
对C#理解不深,使用XmlSerializer序列化时,可以序列化ArrayList,但不能序列化ArrayList[ ]。各位大侠能否帮我想想办法,一个项目因此类型卡住的了?

代码如下:

private void button21_Click(object sender, EventArgs e)
{
ArrayList aList = new ArrayList();
aList.Add("aaa");
aList.Add("bbb");
// XMLSerializer.Serialize(aList, "ArrList.xml"); //序列化ArrayList 没问题的

ArrayList[] listarr = new ArrayList[2];
listarr[0] = new ArrayList();
listarr[1] = new ArrayList();
listarr[0].Add("1");
listarr[0].Add(2);
listarr[1].Add("111");
listarr[1].Add(22.55);

XMLSerializer.Serialize(listarr, "ArrListss.xml");
}



[Serializable]
public class XMLSerializer
{
public static void Serialize(System.Collections.ArrayList[] al,string filePath)
{
try
{
XmlSerializer formatter = new XmlSerializer(typeof(System.Collections.ArrayList[])); //此类型直接出错

//XmlSerializer formatter = new XmlSerializer(typeof(System.Collections.ArrayList));
StreamWriter sw = new StreamWriter(filePath, false);
//formatter.Serialize(sw, al[1]); //可以的
sw.Flush();
sw.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}


XmlSerializer formatter = new XmlSerializer(typeof(System.Collections.ArrayList[])); //此类型直接出错
...全文
708 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
rell336 2015-08-05
  • 打赏
  • 举报
回复
经过多次研究,把源代码的ArrayList[ ]改为ArrayList也不是一件非常麻烦的事情,我现在已经完成,并运行正常。就是把ArrayList[ ]中括号里面的index给去掉,本来是NitTable[0]和NitTable[1]数组2个,添加到ArrayList NitTables下面,2个子ArrayList数组table_nit (实际是根据设备不同而创建1~4个table_nit )。这样就能序列化了,不能就放弃。
宝_爸 2015-07-13
  • 打赏
  • 举报
回复
既然可以用ArrayList,那就用ArryList吧。 一下代码经过测试:

            ArrayList listarr = new ArrayList();

            ArrayList listsub1 = new ArrayList();
            listsub1.Add("1");
            listsub1.Add(2);


            ArrayList listsub2 = new ArrayList();
            listsub2.Add("111");
            listsub2.Add(22.55);

            listarr.Add(listsub1);
            listarr.Add(listsub2);

            XMLSerializer.Serialize(listarr, "ArrListss.xml");

    [Serializable]
    public class XMLSerializer
    {
        public static void Serialize(System.Collections.ArrayList al, string filePath)
        {
            try
            {
                Type typeInfo = al.GetType();
                XmlSerializer formatter = new XmlSerializer(typeInfo); //此类型直接出错

                //XmlSerializer formatter = new XmlSerializer(typeof(System.Collections.ArrayList));
                StreamWriter sw = new StreamWriter(filePath, false);
                formatter.Serialize(sw, al);
                sw.Flush();
                sw.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
结果:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <anyType xsi:type="ArrayOfAnyType">
    <anyType xsi:type="xsd:string">1</anyType>
    <anyType xsi:type="xsd:int">2</anyType>
  </anyType>
  <anyType xsi:type="ArrayOfAnyType">
    <anyType xsi:type="xsd:string">111</anyType>
    <anyType xsi:type="xsd:double">22.55</anyType>
  </anyType>
</ArrayOfAnyType>
fontain2 2015-07-13
  • 打赏
  • 举报
回复
构造一个类实现 IEnumerable 或 ICollection接口就可以了,可以自己枚举,这部分还真得自己写代码,也并不难, foreach(ArrayList al in aList){ //将获得的al序列化为一个字符串,记住规则,将来可以按你的规则反序列化就可以 }
fontain2 2015-07-10
  • 打赏
  • 举报
回复
序列化是需要实现相关接口的,c#里面预定义的实现了,你定义的没实现,如果想序列化一是就如duanzi_peng所言,变通一下没什么,或者你自己写一个类实现相关接口,下面是该类的帮助文档描述 XmlSerializer 特殊处理实现 IEnumerable 或 ICollection 的类。 实现 IEnumerable 的类必须实现包含单个参数的公共 Add 方法。 Add 方法的参数的类型必须与从 Current 属性(此属性在从 GetEnumerator 返回的值上)返回的类型相同,或是该类型的基之一。 除了 IEnumerable 外,实现 ICollection(如 CollectionBase)的类还必须有一个包含整数的公共 Item 索引属性(在 C# 中为索引器),且必须有一个整数类型的公共 Count 属性。 Add 方法的参数类型必须与从 Item 属性返回的类型相同,或者为此类型的基之一。 对于实现 ICollection 的类,从具有索引的 Item 属性检索要序列化的值,而不是通过调用 GetEnumerator。 注意”特殊处理实现 IEnumerable 或 ICollection 的类“这句话
exception92 2015-07-10
  • 打赏
  • 举报
回复
那你就 遍历 ArrayList[] 进行序列化。既然不接受 那个参数类型,就变通呗。
rell336 2015-07-10
  • 打赏
  • 举报
回复
序列化的目的当然是为了反序列化的哈! 楼上解释得很详细,谢谢,但我的确需要“授人以鱼”!!(基础太差的了)不过,遍历后,追加到文件的ArrayList是不能反序列化的啊?! 我所根据楼上的提示,想到的是用一个结构体,ArrayListSt,每个字段存ArrayList[ ]数组的ArrayList,比如ArrayListSt.a0=ArrayList[0],ArrayListSt.a1=ArrayList[1]来解决,序列化ArrayListSt后,反序列化ArrayListSt也能实现(已测试好)。 但,是否我这方法很愚笨?赋值可能很多次的? 因为实际上,ArrayList[ ]数组是嵌入在一个结构体中,其长度也不固定(那么我用我前面方法,就需要将此ArrayList[ ]数组提出来,嵌入到另外的ArrayListSt结构体中)?手动赋值,估计都又得弄半天的 各位,有其他好办法吗?
XML序列化这个东西挺搞人的,当你的Class里有Hashtable这样的东西的时候,在序列化的时候,在XmlSerializer serialize = new XmlSerializer(typeof(myClass));这一句上会出来一个“反射类型时出错”的错误。其实就是那个Hashtable在搞鬼,直接把上面一句换成XmlSerializer serialize = new XmlSerializer(typeof(Hashtable));罪魁祸首就出来了。这次是:“不支持类型 System.Collections.Hashtable,因为它实现 IDictionary”。原来XML序列化时对集合类还有一些比较特殊的要求。  那先来看一个可以正常序列化的集合类――Arraylist:serialize = new XmlSerializer(typeof(ArrayList));在序列化过程中临时生成的文件中可以发现如下的语句: WriteStartElement(@"ArrayOfAnyType", @""); for (int ia = 0; ia < a.Count; ia++) { Write1_Object(@"anyType", @"", ((System.Object)a[ia]), true, false); }WriteEndElement();对于集合类,在XML序列化过程中都是要如上所述来写XML的,显然的,对于实现了IDictionary接口的集合来讲,上面那个for循环是走不通的。因为对于IDictionary来讲Item属性(也就是C#里的[]这个东西,也叫索引器,名字反正有点乱啦)是这样定义的:[C#]object this[ object key] {get; set;} object this[ object key] {get; set;} 上面是从结果上看,猜想最终序列化的时候,集合类是要以上面那样的循环方式进行序列化的,而实现了IDictionary接口的类对于那样的方式是不灵的,所以在生成临时文件的时候就不让它生成了,反正生成的DLL也是无法运行的,直接一个异常出来了。 其实在SDK上可以查到,关于XML序列化有这么一段:XmlSerializer 可以以不同方式处理实现 IEnumerable 或 ICollection 的类(条件是这些类满足某些要求)。实现 IEnumerable 的类必须实现带单个参数的公共 Add 方法。Add 方法的参数必须与从 GetEnumerator 方法返回的 IEnumerator.Current 属性所返回的类型一致(多态)。除实现 IEnumerable 外还实现 ICollection 的类(如 CollectionBase)必须有一个取整数的公共 Item 索引属性(在 C# 中为索引器),并且它必须有一个整数类型的公共 Count 属性。传递给 Add 方法的参数必须与从 Item 属性返回的类型相同或与该类型的某个基的类型相同。对于实现 ICollection 的类,要序列化的值将从索引 Item 属性检索,而不是通过调用 GetEnumerator 来检索。另外请注意,除返回另一个集合类(实现 ICollection 的集合类)的公共字段之外,将不序列化公共字段和属性。无法满足上述条件的都会抛出相应的异常,而实现了IDictionary接口的类显然是无法满足的,.net在实现的时候,一开始就先判断是不是实现了IDictionary接口,发现实现了这个接口的直接就出来了,下面什么Add方法、Item属性呀都不管了。还有一点,就是l 类(Class这一级)――包括集合类与非集合,l 非集合类 需要序列化的属性里的访问方法(不用序列化的属性例外),l 在集合类里,上面提到过的Add方法,Item属性、Count属性、Current属性的访问方法等,如果有过SecurityAttribute声明的也是无法序列化的。不过现在写代码那个SecurityAttribute用得是甚少――这个方面的东西除了照例子依样画葫芦过一下在实践中根本是没有涉足。 要序列化Hashtable其实就只是少一个整数类型的Item属性而已,在这上面是没有什么办法了。想到SortedList这个东西很多方面跟Hashtable差不多,不过它还能依序取得集合中的元素,只是用的不是整数类型的Item属性,而是用GetByIndex()方法。所以就用它来偷梁换柱一下了。// [EnvironmentPermission(SecurityAction.Assert)] public class MyCollection : ICollection { private SortedList list = new SortedList(); public MyCollection () { } // [EnvironmentPermission(SecurityAction.Assert)] public void Add(Item item) { list.Add(item.ID,item); } public Item this[int index] { get {return (Item)list.GetByIndex(index);} } ICollection 成员#region ICollection 成员 public bool IsSynchronized { get { return false; } } public int Count { get { return list.Count; } }      [EnvironmentPermission(SecurityAction.Assert)] public void CopyTo(Array array, int index) { list.CopyTo(array,index); } public object SyncRoot { get { return this; } } #endregion IEnumerable 成员#region IEnumerable 成员 public IEnumerator GetEnumerator() { return list.GetEnumerator(); } #endregion}Item是自定义的一个类。没什么具体的意义。 这样偷一下,上面的这个MyCollection类就是可以被序列化的了,然后把SortedList其他属性包一下,就基本可以当成一个SortedList使用了,说它是Hashtable也差不多吧――外表基本看不出来。不过局限性还是有喽。它的Add方法的参数,与Item属性的类型必须是强类型的,不能用Objcet。用Object类型,临时文件是可以生成,serialize = new XmlSerializer(typeof(Myclass)); 这一句是可以通过没异常了。但真正序列化的时候,除非是一些基本的数据类型,否则它不知道如何去把那个类型写成相应的String,写XML文件就出错了

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧