无法找到程序集异常,执行反序列化时 [英] Unable to find assembly exception,when perform deserialization
问题描述
我的 winforms 应用程序有一个自定义控件,其属性LayoutStream"之一是 byte[]
类型并且它是可序列化的属性.目前我已将我的应用程序从 4.6 框架移植到 NetCore 3.0 项目.
在运行移植的 NetCore 3.0 项目时,我在反序列化 resx 文件中的数据时遇到异常.
this.control1.LayoutStream = ((SerializableByteList)(resources.GetObject("control1.LayoutStream")));公共 SerializableByteList LayoutStream{得到{返回布局流;}放{LayoutStream= 值;如果(值!= null)this.stmLayout.Write(value.Bytes.ToArray(), 0, value.Bytes.ToArray().Length);}}[可序列化]公共类 SerializableByteList{公共 SerializableByteList(){字节数 = 新列表<字节>();}公共列表<字节>字节 { 得到;放;}}
<块引用>
发生异常:抛出异常:System.Runtime.Serialization.Formatters.dll 中的System.Runtime.Serialization.SerializationException"System.Runtime.Serialization.Formatters.dll 中发生类型为System.Runtime.Serialization.SerializationException"的未处理异常无法找到程序集 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
请提出解决此问题的解决方案.
从根本上说,BinaryFormatter
不可移植;它被设计用于在运行相同代码的两个节点之间进行远程处理,而不是在框架之间持久化数据.所以:我的主要建议很简单:
不要使用BinaryFormatter
.曾经.
我意识到这艘船可能已经航行,但一个非常务实的选择是:
- 选择一个新的序列化器——确保它是可移植的(json、xml、protobuf 等);几乎除了
BinaryFormatter
之外的任何东西 - 在旧代码中,使用当前代码反序列化数据,并使用新选择的序列化器单独序列化
- 在您的新代码中,仅将其反序列化为新格式
在 push 时,您可以尝试使用自定义 SerializationBinder
;这里的想法是你将 SerializationBinder
子类化,覆盖方法,并告诉它在哪里可以找到东西.这里的基本问题是:
- 程序集(mscorlib 等)已更改身份
- 类型在许多情况下在程序集之间移动
这两个问题都需要处理.
部分代码:
var bf = new BinaryFormatter { Binder = MyBinder.Instance };//等等
与
class MyBinder : SerializationBinder{私人 MyBinder() { }公共静态 MyBinder 实例 { 获取;} = new MyBinder();公共覆盖类型 BindToType(string assemblyName, string typeName){//TODO: 根据已知列表检查 assemblyName 和 typeName,然后//返回应该使用的类型,通常*而不是*//一个它预期的;}公共覆盖 void BindToName(Type serializedType,out string assemblyName, out string typeName){//TODO:相反}}
<小时>
但这是一项艰苦的工作,而且荒谬脆弱.您的时间将更好地用于移植到不同的序列化程序 IMO.很高兴根据您的需要推荐一些.
<小时>旁注:他们已经反复尝试杀死 .NET Core 的 BinaryFormatter
,但遗憾的是它幸存了下来.
My winforms application has a custom control, one of its property "LayoutStream" is byte[]
type and it is serializable property. Currently I have ported my application from 4.6 framework to NetCore 3.0 project.
While run ported NetCore 3.0 project, im getting below exception when deserialize the data from resx file.
this.control1.LayoutStream = ((SerializableByteList)(resources.GetObject("control1.LayoutStream")));
public SerializableByteList LayoutStream
{
get
{
return LayoutStream;
}
set
{
LayoutStream= value;
if (value != null)
this.stmLayout.Write(value.Bytes.ToArray(), 0, value.Bytes.ToArray().Length);
}
}
[Serializable]
public class SerializableByteList
{
public SerializableByteList()
{
Bytes = new List<byte>();
}
public List<byte> Bytes { get; set; }
}
Exception Occurs: Exception thrown: 'System.Runtime.Serialization.SerializationException' in System.Runtime.Serialization.Formatters.dll An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.Formatters.dll Unable to find assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Please suggest solution to resolve this.
Fundamentally, BinaryFormatter
is not portable; it was designed for remoting between two nodes running identical code, not persisting data between frameworks. So: my main advice is simply:
Don't use
BinaryFormatter
. Ever.
I realise this boat may have sailed, but a very pragmatic option is to:
- pick a new serializer - making sure it is portable (json, xml, protobuf, etc); just about anything except
BinaryFormatter
- in your old code, deserialize the data with your current code, and serialize it separately with the new choice of serializer
- in your new code, deserialize it in the new format only
At a push, however, you could try playing with a custom SerializationBinder
; the idea here is that you subclass SerializationBinder
, override the methods, and tell it where to find things. The fundamental problem here is that:
- the assemblies (mscorlib etc) have changed identity
- types have moved between assemblies in many cases
Both of those problems need handling.
Partial code:
var bf = new BinaryFormatter { Binder = MyBinder.Instance };
// etc
with
class MyBinder : SerializationBinder
{
private MyBinder() { }
public static MyBinder Instance { get; } = new MyBinder();
public override Type BindToType(string assemblyName, string typeName)
{
// TODO: check assemblyName and typeName against some known list, and
// return the Type that should be used, often *instead of* the
// one it expected;
}
public override void BindToName(Type serializedType,
out string assemblyName, out string typeName)
{
//TODO: the opposite
}
}
But this is hard work, and absurdly brittle. Your time would be much better spent porting to a different serializer, IMO. Happy to recommend some, depending on your needs.
Side note: they have tried repeatedly to kill BinaryFormatter
for .NET Core, but it sadly survived.
这篇关于无法找到程序集异常,执行反序列化时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!