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

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控制台应用程序移植到.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。 我得到的例外是:

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?

在调查问题时,我实际上更加困惑,出现了更多的问题:

  • 为什么包含EthernetCatalog类的.NET Framework DLL甚至使用.NET Core中的IPAddress类?
    在.NET Core中引用.NET Framework DLL时,我本以为.NET Framework DLL仍在使用…所有.NET类的.NET Framework版本
  • 属性[System.Serializable]在.NET Core中不再使用了吗?
    当我查看位于的MS.net文档时,有一个可以与BinaryFormatter一起使用的类列表。在查看.NET核心文档时,此列表中的每个类都没有使用属性[System.Serializable]。但是当切换到.NET Framework文档时,属性[System.Serializable]用于所有这些类(我检查了这些类)
  • 提前多谢

  • 为什么包含EthernetCatalog类的.NET Framework DLL甚至使用.NET Core中的IPAddress类
  • 没有。NET有一个类型转发功能,可以使用遗留的.NET Framework标识解析类型。请随意检查.NET Core程序集(路径类似于
    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
    程序集中的新位置。这就是为什么您会收到新标识的错误消息

  • 属性[System.Serializable]在.NET Core中不再使用了吗 是的,但是许多在.NET Framework中可序列化的类在.NET核心中不再可序列化(委托、类型、反射成员、流、编码、区域性信息等)。具有讽刺意味的是,类型转发机制支持序列化,特别是
    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