将代码移入命名空间后出现序列化异常
Serialization exception after moving code into namespace
我将我的 c++/cli (visual studio 2010) 项目的代码移到了命名空间中。在此之前,一切都在全局命名空间中,但这有几个需要解决的缺点。
重命名后,现有存档文件的二进制反序列化失败,错误信息如下:
Serialization Exception occurred.
The object with ID 11 was referenced in a fixup but does not exist.
为了解决 类 的重命名问题 - 现在驻留在命名空间中 - 我使用了 SerializationBinder。
ref class MySerializationBinder sealed: SerializationBinder
{
public:
virtual Type^ BindToType (String^ assemblyname, String^ typeName) override
{
Type^ result = Type::GetType (typeName);
if (result == nullptr)
{
result = Type::GetType ("MyNamespace." + typeName);
}
return result;
}
};
有人知道这里可能出了什么问题吗?
将代码从 How to create a SerializationBinder for the Binary Formatter that handles the moving of types from one assembly and namespace to another 翻译成非常快速的 n 肮脏的 c++ cli,我们得到类似
的东西
virtual Type^ BindToType (String^ assemblyName, String^ typeName) override
{
auto m = Regex::Match (typeName, "^(?<gen>[^\[]+)\[\[(?<type>[^\]]*)\](,\[(?<type>[^\]]*)\])*\]$");
if (m->Success)
{
// generic type
Type^ gen = GetFlatTypeMapping (assemblyName, m->Groups["gen"]->Value);
List<Type^>^ genArgs = gcnew List<Type^> ();
for each(Capture^ c in Enumerable::Cast<Capture^> (m->Groups["type"]->Captures)){
Match^ m2 = Regex::Match (c->Value, "^(?<tname>.*)(?<aname>(,[^,]+){4})$");
String^ tname = m2->Groups["tname"]->Value->Trim ();
Type^ t = BindToType ("", tname);
genArgs->Add(t);
}
return gen->MakeGenericType (genArgs->ToArray ());
}
return GetFlatTypeMapping (assemblyName, typeName);
}
Type^ GetFlatTypeMapping (String^ assemblyName, String^ typeName)
{
Type^ result = Type::GetType (typeName);
if (result == nullptr)
{
result = Type::GetType ("MyNamespace." + typeName);
}
if (result == nullptr)
{
if (typeName->Contains ("BindingList"))
result = BindingList<int>::typeid->GetGenericTypeDefinition (); //int is just a placeholder
if (typeName->Contains ("KeyValuePair"))
result = KeyValuePair<int, int>::typeid->GetGenericTypeDefinition (); //int is just a placeholder
}
if (result == nullptr)
throw gcnew Exception ("Fail");
return result;
}
但是,由于我知道要翻译哪个 类,所以我发现以下方法更容易。这样我们也不必关心嵌套泛型。假定变量 OldClassList
是一个字符串列表,其中包含必须移动到命名空间 MyNamespace
.
中的类名
virtual Type^ BindToType (String^ assemblyName, String^ typeName) override
{
String^ newTypeName = typeName;
for each(String^ name in OldClassList)
newTypeName = Regex::Replace (newTypeName, "(?<![.\w])" + name + "\b", "MyNamespace." + name);
newTypeName = Regex::Replace (newTypeName, "\OldAssembly, Version", "NewAssembly, Version");
Type^ result = Type::GetType (newTypeName);
if (result == nullptr)
throw gcnew Exception ("Could not parse the string {0} to a valid type."->Format(typeName));
return result;
}
我将我的 c++/cli (visual studio 2010) 项目的代码移到了命名空间中。在此之前,一切都在全局命名空间中,但这有几个需要解决的缺点。
重命名后,现有存档文件的二进制反序列化失败,错误信息如下:
Serialization Exception occurred.
The object with ID 11 was referenced in a fixup but does not exist.
为了解决 类 的重命名问题 - 现在驻留在命名空间中 - 我使用了 SerializationBinder。
ref class MySerializationBinder sealed: SerializationBinder
{
public:
virtual Type^ BindToType (String^ assemblyname, String^ typeName) override
{
Type^ result = Type::GetType (typeName);
if (result == nullptr)
{
result = Type::GetType ("MyNamespace." + typeName);
}
return result;
}
};
有人知道这里可能出了什么问题吗?
将代码从 How to create a SerializationBinder for the Binary Formatter that handles the moving of types from one assembly and namespace to another 翻译成非常快速的 n 肮脏的 c++ cli,我们得到类似
的东西virtual Type^ BindToType (String^ assemblyName, String^ typeName) override
{
auto m = Regex::Match (typeName, "^(?<gen>[^\[]+)\[\[(?<type>[^\]]*)\](,\[(?<type>[^\]]*)\])*\]$");
if (m->Success)
{
// generic type
Type^ gen = GetFlatTypeMapping (assemblyName, m->Groups["gen"]->Value);
List<Type^>^ genArgs = gcnew List<Type^> ();
for each(Capture^ c in Enumerable::Cast<Capture^> (m->Groups["type"]->Captures)){
Match^ m2 = Regex::Match (c->Value, "^(?<tname>.*)(?<aname>(,[^,]+){4})$");
String^ tname = m2->Groups["tname"]->Value->Trim ();
Type^ t = BindToType ("", tname);
genArgs->Add(t);
}
return gen->MakeGenericType (genArgs->ToArray ());
}
return GetFlatTypeMapping (assemblyName, typeName);
}
Type^ GetFlatTypeMapping (String^ assemblyName, String^ typeName)
{
Type^ result = Type::GetType (typeName);
if (result == nullptr)
{
result = Type::GetType ("MyNamespace." + typeName);
}
if (result == nullptr)
{
if (typeName->Contains ("BindingList"))
result = BindingList<int>::typeid->GetGenericTypeDefinition (); //int is just a placeholder
if (typeName->Contains ("KeyValuePair"))
result = KeyValuePair<int, int>::typeid->GetGenericTypeDefinition (); //int is just a placeholder
}
if (result == nullptr)
throw gcnew Exception ("Fail");
return result;
}
但是,由于我知道要翻译哪个 类,所以我发现以下方法更容易。这样我们也不必关心嵌套泛型。假定变量 OldClassList
是一个字符串列表,其中包含必须移动到命名空间 MyNamespace
.
virtual Type^ BindToType (String^ assemblyName, String^ typeName) override
{
String^ newTypeName = typeName;
for each(String^ name in OldClassList)
newTypeName = Regex::Replace (newTypeName, "(?<![.\w])" + name + "\b", "MyNamespace." + name);
newTypeName = Regex::Replace (newTypeName, "\OldAssembly, Version", "NewAssembly, Version");
Type^ result = Type::GetType (newTypeName);
if (result == nullptr)
throw gcnew Exception ("Could not parse the string {0} to a valid type."->Format(typeName));
return result;
}