上下文如下
- 我想通过将代码移动到不同的项目来重构代码
- 其中一些代码包含用于跨多个端点发送和接收数据的可序列化 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
}
}