【问题标题】:Deserializing List<IList>反序列化列表<IList>
【发布时间】:2021-09-23 11:17:04
【问题描述】:

我正在将一组应用程序从 .Net Framework 4.7 迁移到 .Net 5.0,但在反序列化方面遇到了一些问题。

下面的示例说明了我面临的问题。如果这两个应用程序都是 .Net 框架,它可以正常工作。如果两者都是.Net 5.0,它工作正常。但是,如果一个应用程序是 .Net 4.7 而另一个是 5.0,则在反序列化类型 List&lt;IList&gt; 时会出现异常。

.Net 5.0 应用程序CreateData

using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Test;

namespace CreateData
{
    class Program
    {
        static void Main()
        {
            DataStructure dataStructure = new DataStructure();

            ArrayList arrayList = new ArrayList();
            arrayList.Add(42);
            dataStructure.data.Add(arrayList);

            // Open a stream for writing
            FileStream fs = new FileStream(@"C:\DataFile.dat", FileMode.Create);
            
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs, dataStructure);
            fs.Close();

            Console.WriteLine("Data file created, press Enter to exit");
            Console.ReadLine();
        }
    }
}

.Net Standard 2.0 库Lib

using System;
using System.Collections;
using System.Collections.Generic;

namespace Test
{
    [Serializable]
    public class DataStructure
    {
        public DataStructure()
        {
            data = new List<IList>();
        }

        public List<IList> data;
    }
}

.Net 4.7 应用程序ReadData

using System;
using System.Linq;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Test;


namespace ReadData
{
    class Program
    {
        static void Main()
        {
            DataStructure dataStructure = new DataStructure();

            // Open the data file
            FileStream fs =  new FileStream(@"C:\DataFile.dat",FileMode.Open);

            // Construct the binary formatter
            BinaryFormatter bf = new BinaryFormatter();
            
            // deserialize
            dataStructure = (DataStructure) bf.Deserialize(fs);
            fs.Close();

            // Announce success
            Console.WriteLine("Value = {0}", dataStructure.data.First()[0]);
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }
    }
}

System.Runtime.Serialization.SerializationException:无法加载 类型 System.Collections.Generic.List`1[[System.Collections.IList, System.Private.CoreLib,版本=5.0.0.0,文化=中性, 反序列化需要 PublicKeyToken=7cec85d7bea7798e]]。在 System.Runtime.Serialization.ObjectManager.CompleteObject(ObjectHolder 持有人,布尔 bObjectFullyComplete) 在 System.Runtime.Serialization.ObjectManager.DoNewlyRegisteredObjectFixups(ObjectHolder 持有人)在 System.Runtime.Serialization.ObjectManager.RegisterObject(对象 obj, Int64 objectID, SerializationInfo info, Int64 idOfContainingObj, MemberInfo 成员,Int32[] arrayIndex) 在 System.Runtime.Serialization.Formatters.Binary.ObjectReader.RegisterObject(对象 obj, ParseRecord pr, ParseRecord objectPr, Boolean bIsString) at System.Runtime.Serialization.Formatters.Binary.ObjectReader.RegisterObject(对象 obj, ParseRecord pr, ParseRecord objectPr) 在 System.Runtime.Serialization.Formatters.Binary.ObjectReader.ParseObjectEnd(ParseRecord 公关)在 System.Runtime.Serialization.Formatters.Binary.ObjectReader.Parse(ParseRecord 公关)在 System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
在 System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler 处理程序,__BinaryParser serParser,布尔 fCheck,布尔 isCrossAppDomain, IMethodCallMessage methodCallMessage) 在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流 serializationStream, HeaderHandler 处理程序, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) 在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流 serializationStream、HeaderHandler 处理程序、布尔 fCheck、 IMethodCallMessage methodCallMessage) 在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流 序列化流,HeaderHandler 处理程序,布尔 fCheck)在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流 序列化流,HeaderHandler 处理程序)在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流 serializationStream) 在 ReadData.Program.Main() in

有没有办法加载类型System.Collections.Generic.List1[[System.Collections.IList, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]?我该怎么做才能解决这个问题?

如果可能的话,我想一次迁移一个应用程序,而不是一次性迁移整个代码库。

谢谢!

【问题讨论】:

  • 也许您需要像这样更改活页夹:stackoverflow.com/a/7154652/1724128
  • 老实说,BinaryFormatter 只会继续伤害你;它现在有效地被废弃和弃用了;更改序列化程序是一种选择吗?
  • 部分迁移可能必须远离这种序列化;这样做时可能值得坚持使用 .NET Framework,这样过渡会更加顺畅。
  • @JeroenMostert 没错。已经有很多松散的结局,所以我真的不想改变序列化(尽管我同意它最终需要完成)
  • 好吧,我的论点是,当您忙于更改序列化时,您可能还应该忙于迁移到 .NET 5 . :) 请记住,.NET Framework 将在很长一段时间内得到支持,尽管已经投入了所有工作,但对于某些项目来说,它不会是一个直接升级。二进制序列化绝对是受到严重影响的领域之一。微软真的很想完全摆脱这种局面,所以准备好继续前进吧。跨框架兼容性永远不会出现在功能列表中。

标签: c#


【解决方案1】:

恭喜!您已经找到了一个不使用 BinaryFormatter 的原因。其他原因包括安全性、性能和尺寸。我建议尽快切换到其他任何东西。

管理序列化的推荐方法是将用于序列化的类型与包含实际逻辑的类型分开。这允许为各自的目的调整各自的类型。诸如向后兼容之类的事情更简单,因为通常可以进行诸如添加属性之类的事情,并且您可以选择保留同一类型的多个版本,以防类型结构发生较大变化。

我还强烈建议设置单元测试,以测试不同类型的序列化/反序列化是否正确。但是单元测试通常也是一个非常有用的工具,可以用来了解序列化库的可能性。

您也许可以执行type-mapping 之类的操作,但在我看来,这是一个巨大的障碍。将类型更改为数组而不是列表也可能会有所帮助,但是如果您要更改序列化格式,则最好切换到更好的格式。也许可以在 .net 4.7 中编写一个转换器来在旧格式和新格式之间进行转换。

【讨论】:

    猜你喜欢
    • 2017-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多