将继承的arraylist反序列化为继承的列表<>

时间:2012-01-05 08:55:03

标签: c# list generics arraylist

我正在使用ArrayLists转换我的应用程序以开始使用List<>

我之前发过关于这个主题的帖子,但确实留下了很多细节。这是一篇新帖子,其中包含完整的详细信息以及从另一个角度描述的问题。

在转换之前,代码看起来与此类似:

[Serializable]
public class TestContainer1 : ISerializable
{
  public TestContainer1()
  {
    TestList.Add(1);
    TestList.Add(2);
    TestList.Add(3);
  }
  public void GetObjectData(SerializationInfo info, StreamingContext context)
  {
    info.AddValue("List1", TestList);
  }
  protected TestContainer1(SerializationInfo info, StreamingContext context)
  {
    TestList = (TestClass1)info.GetValue("List1", typeof(TestClass1));
  }
  public TestClass1 TestList = new TestClass1();
}
[Serializable]
public class TestClass1 : ArrayList
{
  public TestClass1(){}
  public DateTime Startdate = DateTime.Today;
  public int SomeValue = 127;
}

当它保存到文件时,使用了以下代码(稍微简化):

TestContainer1 tc = new TestContainer1();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, tc);  //fs is a file stream

此时,保存了一个TestContainer1实例,其中包含TestClass1实例(TestList属性)。此TestList确实包含3个值(1,2和3)的列表,以及2个属性(Startdate和SomeValue)。

现在,我想使用通用列表转换我的结构。我的课程定义如下:

[Serializable]
public class TestContainer2 : ISerializable
{
  public TestContainer2()   {}
  public void GetObjectData(SerializationInfo info, StreamingContext context)
  {
    info.AddValue("List1", TestList);
  }
  protected TestContainer2(SerializationInfo info, StreamingContext context)
  {
    TestList = (TestClass2)info.GetValue("List1", typeof(TestClass2));
  }
  public TestClass2 TestList = new TestClass2();
}
[Serializable]
public class TestClass2 : List<int>//, ISerializable
{
  public TestClass2() {}
  public DateTime Startdate;
  public int SomeValue;
}

这些类有新名称,但这只是为了将它们与旧版本区分开来(TestContainer1和TestClass1)。

当我现在尝试反序列化以前保存的数据时,我使用代码:

BinaryFormatter formatter = new BinaryFormatter();
//Deserialize it to a new object
formatter.Binder = new TestTypeBinder();
TestContainer2 tc2 = (TestContainer2)formatter.Deserialize(ms);

我正在使用绑定器将数据反序列化为具有新名称的类(TestContainer2和TestClass2)

binder类看起来像:

sealed class TestTypeBinder : SerializationBinder
{
  public override Type BindToType(string assemblyName, string typeName)
  {
    Type typeToDeserialize = null;
    String typeVer1_1 = "SimDataStorage.DataStorage+TestContainer1";
    String typeVer1_2 = "SimDataStorage.DataStorage+TestClass1";
    String typeVer2_1 = "SimDataStorage.DataStorage+TestContainer2";
    String typeVer2_2 = "SimDataStorage.DataStorage+TestClass2";

    if (typeName == typeVer1_1)
      typeName = typeVer2_1;
    else if (typeName == typeVer1_2)
      typeName = typeVer2_2;

    typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
      typeName, assemblyName));                 

    return typeToDeserialize;
  }
}

活页夹按预期工作。调用TestContainer2的反序列化函数,并对TestClass2进行反序列化。

最大的问题是TestList(它现在是TestClass2的一个实例,它继承自List而不是ArrayList)变为空。

我尝试使用如下代码转换TestList:

Type unspec = typeof(List<>);
Type spec = unspec.MakeGenericType(typeof(int));
object obj = formatter.Deserialize(ms);
Type ut = ((ArrayList)obj)[0].GetType();
object typeInst = Activator.CreateInstance(spec, ((ArrayList)obj).ToArray(ut));

这样可以填充TestContainer2类中的TestList,但不会反序列化TestClass2实例中的Enddate和SomeValue属性。

是否存在将我以前保存的Arraylist派生类转换为我的新List&lt;&gt; -derived类的简单方法? 谢谢 /弗雷德里克

1 个答案:

答案 0 :(得分:1)

我有一种感觉,你想要做的事情是不可能的。我建议您在解决方案中保留旧TestClass1的副本,并编写一个手动转换器,通过标准属性赋值将反序列化的TestClass1转换为TestClass2。

如果TestContainer1成功反序列化为TestContainer2,则可以将TestClass1到TestClass2的转换挂钩到TestContainer2的OnDeserializing上。