Десериализация наследованного массива в унаследованный список <> - PullRequest
0 голосов
/ 05 января 2012

Я перевожу свое приложение из 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)

СвязывательКласс выглядит так:

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));

Это работает так, что TestList в классе TestContainer2 становится заполненным, но атрибуты Enddate и SomeValue вЭкземпляр TestClass2 не десериализован.

Существует ли какой-либо простой способ преобразования ранее сохраненных классов, полученных из Arraylist, в мои новые классы, производные от List <>?Спасибо / Фредрик

1 Ответ

1 голос
/ 05 января 2012

У меня ощущение, что ты пытаешься сделать это невозможно.Я бы предложил вам вместо этого сохранить копию старого TestClass1 в своем решении и написать ручной конвертер, который преобразует десериализованные TestClass1 в TestClass2 с помощью стандартного присвоения свойств.

Если TestContainer1 успешно десериализуется в TestContainer2, вы можете подключить преобразование TestClass1 к TestClass2 к OnDeserializing из TestContainer2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...