上下文如下
- 我想通过将代码移动到不同的项目来重构代码
- 其中一些代码包含可序列化的 DTO,用于
跨多个端点发送和接收数据
- 如果我移动代码,序列化就会中断(因此它不是
向后兼容我的应用程序的旧版本)
这个问题的一个解决方案是 SerializationBinder,它允许我在某种意义上从一种类型“重定向”到另一种类型。
因此我想创建一个SerializationBinder来满足这个需求。但是,必须满足以下要求才能做到这一点
- SerializationBinder 的输入应该是旧类型的列表
到新的类型映射。映射应包括旧程序集
名称(无版本,无公钥令牌)和旧的全名
类型(命名空间和名称)以及新的程序集名称和新的
类型的全名
- 对于输入中的类型,应忽略程序集的版本号
- 如果我的类型恰好在泛型中,它应该处理泛型
(列表、字典等)无需在输入中包含泛型
- 对于输入中未包含的任何内容(即未包含在输入中的类型)
例如移动或 .NET 类型(例如数据集),它应该默认为
使用二进制序列化器的开箱即用算法
这是可能的还是我在做梦?是否已经有一些东西可以做到这一点?我认为这是一个常见问题。
到目前为止,我认为没有简单的方法可以做到 3,也没有办法做到 4。
这是一个尝试
public class SmartDeserializationBinder : SerializationBinder
{
/// <summary>
/// Private class to handle storing type mappings
/// </summary>
private class TypeMapping
{
public string OldAssemblyName { get; set; }
public string OldTypeName { get; set; }
public string NewAssemblyName { get; set; }
public string NewTypeName { get; set; }
}
List<TypeMapping> typeMappings;
public SmartDeserializationBinder()
{
typeMappings = new List<TypeMapping>();
}
public void AddTypeMapping(string oldAssemblyName, string oldTypeName, string newAssemblyName, string newTypeName)
{
typeMappings.Add(new TypeMapping()
{
OldAssemblyName = oldAssemblyName,
OldTypeName = oldTypeName,
NewAssemblyName = newAssemblyName,
NewTypeName = newTypeName
});
}
public override Type BindToType(string assemblyName, string typeName)
{
//Need to handle the fact that assemblyName will come in with version while input type mapping may not
//Need to handle the fact that generics come in as mscorlib assembly as opposed to the assembly where the type is defined.
//Need to handle the fact that some types won't even be defined by mapping. In this case we should revert to normal Binding... how do you do that?
string alternateAssembly = null;
string alternateTypeName = null;
bool needToMap = false;
foreach (TypeMapping mapping in typeMappings)
{
if (typeName.Contains(mapping.OldTypeName))
{
alternateAssembly = mapping.NewAssemblyName;
alternateTypeName = mapping.NewTypeName;
needToMap = true;
break;
}
}
if (needToMap)
{
bool isList = false;
if (typeName.Contains("List`1"))
isList = true;
// other generics need to go here
if (isList)
return Type.GetType(String.Format("System.Collections.Generic.List`1[[{0}, {1}]]", alternateTypeName, alternateAssembly));
else
return Type.GetType(String.Format("{0}, {1}", alternateTypeName, alternateAssembly));
}
else
return null; // this seems to do the trick for binary serialization, but i'm not sure if it is supposed to work
}
}