Обновление объекта данных с использованием SerializationBinder и Surrogate

Я получаю объект типа "Project1.Class1[]", который нельзя преобразовать в тип "Project2.Class1[]". при попытке перенести данные из проекта 1 класса 1 в проект 2

Передаваемый объект - это список Project1.Class1, который содержит подобъект Class2. Итак, я создал два суррогатных класса для обработки преобразования объектов, но я получаю эту ошибку до того, как суррогаты обрабатывают обновление списка Class1.

[Serializable]
internal class Class1Upgrader
{
   public BinaryFormatter CreateFormatter()
   {
      BinaryFormatter binaryFormatter = new BinaryFormatter();
      SurrogateSelector selector = new SurrogateSelector();
      selector.AddSurrogate(typeof(Project1.Class1), new StreamingContext(StreamingContextStates.All), new Class1Surrogate());
      selector.AddSurrogate(typeof(Project1.Class2), new StreamingContext(StreamingContextStates.All), new Class2Surrogate());
      binaryFormatter.SurrogateSelector = selector;
      binaryFormatter.Binder = new Class1Binder();

      return binaryFormatter;
   }
}

[Serializable]
internal class Class1Binder : SerializationBinder
{
  public override Type BindToType(string assemblyName, string typeName)
  {
     if (typeName == typeof(List<Project1.Class1>).FullName)
     {
        return typeof(List<Project2.Class1>);
     }
     return null;
  }
}

Изменить: после исправления проблемы это решение станет огромным подспорьем для людей, которым необходимо обновить поля varbinary в SQL в C#. Большинство корней кода лежат в основе того, чтобы люди начали.:)

1 ответ

Решение
[Serializable]
internal class Class1Upgrader
{
  public BinaryFormatter CreateFormatter()
  {
     BinaryFormatter binaryFormatter = new BinaryFormatter();
     SurrogateSelector selector = new SurrogateSelector();
     selector.AddSurrogate(typeof(Project2.Class1), new StreamingContext(StreamingContextStates.All), new Class1Surrogate());
     selector.AddSurrogate(typeof(Project1.Class2), new StreamingContext(StreamingContextStates.All), new Class2Surrogate());
     binaryFormatter.SurrogateSelector = selector;
     binaryFormatter.Binder = new Class1Binder();
     return binaryFormatter;
  }
}

[Serializable]
internal class Class1Binder : SerializationBinder
{
  public override Type BindToType(string assemblyName, string typeName)
  {
    if (typeName.Contains("System.Collections.Generic.List`1[[Project1.Class1, Class1"))
    {
       return typeof(List<Project2.Class1>);
    }
    if (typeName == typeof(Project1.Class1).FullName)
    {
       return typeof(Project2.Class1);
    }
    return null;
  }
}

internal class Class1Surrogate : ISerializationSurrogate
{
   public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
   {
     Project2.Class1 result = (Project2.Class1)obj;
     //Handle the logic here to convert your old properties into your new one
     return result;
   }
   public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
   {
     throw new NotImplementedException();
   }
}

internal class Class2Surrogate : ISerializationSurrogate
{
   public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
   {
     Project2.Class1 result = new Project2.Class1();
     //Handle the logic here to convert your old properties into your new one
     return result;
   }
   public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
   {
     throw new NotImplementedException();
   }
}

Итак, решение состоит в том, чтобы изменить привязку, чтобы вернуть новый объект, а не старый, который будет передан через суррогат. Это важно при работе со списком объекта, который вы пытаетесь обновить. Итак, добавив typeof(Project2.Class1), суррогатный класс обработает преобразование ваших свойств. Таким образом, в вашем SetObjectData в суррогате в объекте будет typeof(Project2.Class1), как показано выше в Class1Surrogate.

Другие вопросы по тегам