移动类时保持.NET序列化数据的兼容性

doo*_*bop 2 .net serialization soap

我有序列化的数据.与序列化数据相关联的类是大型遗留项目的一部分,该项目具有许多第三方引用,这些引用对于此核心数据集不是必需的.现在我需要将这些数据读入另一个应用程序.我想将数据类重构为一个单独的项目,该项目可以在2个应用程序之间共享,因此我最终不需要所有第三方库.我还想保持与之前保存的数据的兼容性.我不需要更改类中的任何字段,只需要更改它们所在的项目.

到目前为止,我已经将课程转移到了一个新项目.我保留了名称空间与旧项目中的名称空间相同.但是,这还不足以读取对象.我收到一个SerializationException,指出"解析错误,没有与Xml密钥相关的类型a1 MyCorp.MyApp.DatabaseRoot MyCorp.MyApp".查看SOAP生成的XML,引用的模式已更改.例如,我最初在项目DashboardLibrary中有一个类MyCorp.Dashboard.DatabaseRoot.这被移动到项目DashboardData(但仍使用命名空间MyCorp.Dashboard.DatabaseRoot).XML以这种方式改变了:

Orig: <a1:DatabaseRoot id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/MyCorp.Dashboard/MyCorp.Dashboard">
New:  <a1:DatabaseRoot id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/MyCorp.Dashboard/DashboardData">
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是

  • 是否可以移动类并保持兼容性?我似乎接近将它拉下来.
  • 如果是这样,我如何控制最后一位模式信息(MyCorp.Dashboard与DashboardData).原始似乎基于目录位置,而第二个是项目名称.我已经尝试在新项目中更改目录结构,但没有运气.还有什么我想念的吗?

谢谢.

Tho*_*que 5

您需要实现自定义SerializationBinder.重写BindToType方法以根据其名称选择要加载的类型:

public override Type BindToType(string assemblyName, string typeName)
{
    if (assemblyName == "MyOldAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
    {
        if (typeName == "MyOldNamespace.MyOldClass")
        {
            return typeof(MyNewClass);
        }
    }
    // Fall back to the default behavior, which will throw
    // a SerializationException if the old assembly can't be found
    return null;
}
Run Code Online (Sandbox Code Playgroud)

(这是一个非常基本的实现,在实际场景中,您可能会使用更好的映射逻辑).

BindToName如果需要重新序列化数据,也可以覆盖旧程序集仍可读取的数据.这允许您自定义序列化对象的程序集和类型名称.

获得自定义后SerializationBinder,只需将其分配给Binder格式化程序的属性,并从那里正常使用它.

如果需要更改类型的结构(添加或重命名字段,更改类型...),则需要实现a ISerializationSurrogate以将旧数据映射到新类型结构.