gpt4 book ai didi

c# - 在 .NET Core 3 中反序列化使用 .NET Framework 创建的二进制文件时出现问题

转载 作者:行者123 更新时间:2023-12-05 05:03:48 31 4
gpt4 key购买 nike

你好,

我尝试将 .NET Framework 控制台应用程序移植到 .NET Core 3.0。但是当我启动核心版本时,我在反序列化二进制文件时遇到异常。
此二进制文件是在另一个 .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。我得到的异常(exception)是:

System.Runtime.Serialization.SerializationException: 'Type 'System.Net.IPAddress' in Assembly 'System.Net.Primitives, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable.'

显然在 EthernetCatalog 类的某处使用了 IPAddress 类。此类在 .NET Framework 中可序列化,但在 .NET Core 中不可序列化。

所以我的第一个问题是你能做到这一点吗?尽管 EthernetCatalog 类是在 .NET Framework DLL 中定义的,但我可以在 .NET Core 中反序列化包含 EthernetCatalog 对象的文件吗?比如告诉 Deserilized 只是将所有无法反序列化的内容设置为 null?

在调查这个问题时,我实际上变得更加困惑,并且出现了更多问题:

  1. 为什么包含 EthernetCatalog 类的 .NET Framework DLL 甚至使用 .NET Core 中的 IPAddress 类?
    在 .NET Core 中引用 .NET Framework DLL 时,我本以为 .NET Framework DLL 仍在使用……好吧,所有 .NET 类的 .NET Framework 版本。
  2. .NET Core 中是否不再使用 [System.Serializable] 属性?
    当我在 https://learn.microsoft.com/en-us/dotnet/standard/serialization/binary-serialization 查看 MS .net 文档时有一个可与 BinaryFormatter 一起使用的类列表。并且在查看 .NET Core 文档时,此列表中的每个类都没有使用 [System.Serializable] 属性。但是当切换到 .NET Framework 文档时,属性 [System.Serializable] 用于所有这些类(我检查过)。

提前致谢!

最佳答案

  1. Why is the .NET Framework DLL containing the EthernetCatalog class even using the IPAddress class from .NET Core?

事实并非如此。 .NET 具有类型转发功能,可以使用其旧的 .NET Framework 标识解析类型。随时检查 .NET Core 程序集(路径类似于 C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.0.0),您会发现 System.dll 甚至在 .NET Core 中(IPAddress 位于 .NET Framework 中)。但是尝试反汇编它,你会发现它不包含任何类型,而是一堆程序集属性。其中:

[assembly: TypeForwardedTo(typeof(IPAddress))]

其中 IPAddress 引用该类型在 System.Net.Primitives 程序集中的新位置。这就是您收到有关新身份的错误消息的原因。

  1. Is the attribute [System.Serializable] not used anymore in .NET Core?

是的,但是许多在 .NET Framework 中可序列化的类在 .NET Core 中不再可序列化(委托(delegate)、类型、反射成员、流、编码、文化信息等)。具有讽刺意味的是,类型转发机制是支持序列化的,特别是 BinaryFormatter 机制,但似乎有一些类型不再可序列化,但它们仍然被转发。

可能的解决方案:

根据经验,如果您需要跨平台序列化对象,您应该更喜欢一些基于文本的序列化,例如 XML 或 JSON。

但即使您确实需要使用 BinaryFormatter 反序列化遗留流,也有一些可能的解决方法。

  1. 设置BinaryFormatterSurrogateSelector 属性来自定义某些类型的反序列化。如果您使用我的 CustomSerializerSurrogateSelector 可能是最简单的解决方案,正是为了这个目的。来自其文档:
// deserializing a MemoryStream in .NET Core that was serialized in .NET Framework
var formatter = new BinaryFormatter { SurrogateSelector = new CustomSerializerSurrogateSelector() };
var memoryStream = (MemoryStream)formatter.Deserialize(streamSerializedInNetFramework);

如您所见,我将它用于MemoryStream,但它也应该以同样的方式用于IPAddress。您可以从 nuget 下载库。

  1. 另一种解决方案是使用必须分配给二进制格式化程序的 Binder 属性的 SerializationBinder:将 IPAddress 重定向到自定义可序列化类,应实现 IObjectReference。您必须实现 GetRealObject 方法,该方法必须返回正确的 IPAddress 实例。

关于c# - 在 .NET Core 3 中反序列化使用 .NET Framework 创建的二进制文件时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61455857/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com