C# 在.NET Core 3中反序列化使用.NET Framework创建的二进制文件时出现问题
你好 我尝试将.NET Framework控制台应用程序移植到.NET Core 3.0。但是,当我启动核心版本时,在二进制文件被反序列化的地方会出现异常。C# 在.NET Core 3中反序列化使用.NET Framework创建的二进制文件时出现问题,c#,.net,.net-core,deserialization,C#,.net,.net Core,Deserialization,你好 我尝试将.NET Framework控制台应用程序移植到.NET Core 3.0。但是,当我启动核心版本时,在二进制文件被反序列化的地方会出现异常。 此二进制文件是在另一个.NET Framework程序中使用BinaryFormatter类通过对象序列化创建的。 为了反序列化它,我引用了包含序列化类的DLL。 因此,从控制台应用程序截取的代码是: IFormatter formatter = new BinaryFormatter(); Stream
此二进制文件是在另一个.NET Framework程序中使用BinaryFormatter类通过对象序列化创建的。
为了反序列化它,我引用了包含序列化类的DLL。 因此,从控制台应用程序截取的代码是:
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
EthCatalog = (EthernetCatalog)formatter.Deserialize(stream);
其中EthernetCatalog来自引用的DLL。
我得到的例外是:
System.Runtime.Serialization.SerializationException:“程序集System.Net.Primitives,版本=4.1.1.0,区域性=中性,PublicKeyToken=b03f5f7f11d50a3a”中的类型“System.Net.IPAddress”未标记为可序列化。”
显然,在EthernetCatalog类的某个地方使用了IPAddress类。此类可在.NET Framework中序列化,但不能在.NET Core中序列化
所以我的第一个问题是,你能做到这一点吗?尽管EthernetCatalog类是在.NET Framework DLL中定义的,但我是否可以反序列化.NET Core中包含EthernetCatalog对象的文件?比如,告诉反序列化的用户只需将无法反序列化的所有内容设置为null?
在调查问题时,我实际上更加困惑,出现了更多的问题:
在.NET Core中引用.NET Framework DLL时,我本以为.NET Framework DLL仍在使用…所有.NET类的.NET Framework版本
当我查看位于的MS.net文档时,有一个可以与BinaryFormatter一起使用的类列表。在查看.NET核心文档时,此列表中的每个类都没有使用属性[System.Serializable]。但是当切换到.NET Framework文档时,属性[System.Serializable]用于所有这些类(我检查了这些类)
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.0.0
),您甚至可以在.NET Core中找到System.dll
(其中IPAddress
位于.NET Framework中)。但是尝试反汇编它,您将看到它不包含任何类型,而是一组程序集属性。除其他外:
[assembly: TypeForwardedTo(typeof(IPAddress))]
其中,IPAddress
引用类型在System.Net.Primitives
程序集中的新位置。这就是为什么您会收到新标识的错误消息
BinaryFormatter
机制,但似乎有一些类型不再可序列化,它们仍然被转发
可能的解决方案:
根据经验,如果您需要跨平台序列化对象,您应该更喜欢一些基于文本的序列化,例如XML或JSON
但是,即使您确实需要使用BinaryFormatter
反序列化遗留流,也有一些可能的解决方法
BinaryFormatter
的代理选择器
属性以自定义某些类型的反序列化。如果您使用my,可能是最简单的解决方案,这正是为此目的。根据其文件://反序列化.NET内核中在.NET Framework中序列化的MemoryStream
var formatter=new BinaryFormatter{subscrateselector=new CustomSerializerSurrogateSelector()};
var memoryStream=(memoryStream)格式化程序。反序列化(streamserializedinetframework);
正如您所看到的,我在MemoryStream
中使用了它,但在IPAddress
中也应该使用同样的方法。您可以从
Binder
属性的SerializationBinder
:将IPAddress
重定向到自定义可序列化类,该类应实现IObjectReference
。您必须实现GetRealObject
方法,该方法必须返回正确的IPAddress
实例类对象具有簿记值,这些值随数据序列化很长一段时间。仅当数据和预订值与序列化时相同时,反序列化才起作用。我知道,当您更改序列化的网络版本以使其工作时,必须重新编译。因此,请确保您进行了干净的构建,以确保所有中间对象文件都使用您正在使用的核心版本重新编译。谢谢您的回答。我还没有尝试过你建议的解决方案,但只是想评论一下你回答中的一点:你说[System.Serializable]仍然在.NETCore中使用。但是如果你看这里:它说明你可以使用数组类和.NET Core中的BinaryFormatter,但是如果你点击你看不到[System.Serializable],当它还在这里时,生成的文档并不完美。但是.NET Core中的
Array
(当然,这也取决于元素类型)。你好,我尝试了你的nuget软件包和代理Selector=new CustomSerializerUrrogateSelector()选项,但现在我得到了异常System.ArgumentException:'Typ