首页 > 解决方案 > 使用 SerializationBinder 和 Surrogate 更新数据对象

问题描述

我得到一个“Project1.Class1[]”类型的对象无法转换为“Project2.Class1[]”类型。尝试将数据从 class1 项目 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;
  }
}

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

标签: c#sqlvarbinarybinaryformatterserializationbinder

解决方案


[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 中所示。


推荐阅读