使用 SerializationBinder 和 Surrogate 更新数据对象

Data object update using SerializationBinder and Surrogate

我得到一个 'Project1.Class1[]' 类型的对象无法转换为 'Project2.Class1[]' 类型。'当试图将数据从 class1 项目 1 取到项目 2

传递的对象是包含 Class2 子对象的 Project1.Class1 列表。所以我创建了两个 Surrogate 类 来处理对象的转换,但是在代理处理更新 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;
  }
}

编辑:解决问题后,此解决方案将对需要在 C# 中更新 SQL 中的 varbinary 字段的人们提供巨大帮助。大多数代码根都在让人们开始的答案中。 :)

[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();
   }
}

所以解决方案是将活页夹更改为 return 新对象而不是要通过代理项传递的旧对象。这在使用您尝试升级的对象的列表时很重要。因此,添加 typeof(Project2.Class1) 代理项 class 将处理您的属性转换。因此,在您的 SetObjectData 中,对象中的代理项将是 typeof(Project2.Class1),如上面在 Class1Surrogate 中所示。