在应用程序之间共享序列化对象

本文关键字:序列化 对象 共享 之间 应用程序 | 更新日期: 2023-09-27 18:12:41

在应用程序1中,我序列化和反序列化一个对象,它工作得很好。然而,我想在应用程序2中反序列化应用程序1中的对象。我将定义该对象的类添加到应用程序2中。当我试图反序列化它时,我得到这个错误:

无法找到程序集'WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

如何在两个应用程序之间共享序列化对象呢?

在应用程序之间共享序列化对象

将可序列化对象的定义放入单独的程序集,然后将对共享程序集的引用添加到每个项目。(格式化程序在您的第一个项目中添加了对程序集的引用-它们实际上必须引用相同的类,而不仅仅是类的相同副本)

如果您使用的是BinaryFormatter,那么它在数据中包含完整的类型名称,其中包括DTO所在的程序集(类型总是由它们的程序集定义)。这里的一个选择是创建一个单独的DTO库,您可以从每个DTO库中引用-但请注意,BinaryFormatter在版本控制方面仍然非常不可靠:我曾见过有人丢失数据,因为他们编辑了他们的DTO,然后一切都停止了工作。

我强烈建议使用非类型依赖的序列化器;例如,XmlSerializer/DataContractSerializer/JSON.NET/ServiceStack的JsonSerializer,或protobuf-net。所有这些都可以很好地工作,但重要的是,不会以两种不同的方式与对抗:

  • 他们是非常版本友好的
  • 它们不关心你是否在程序集之间移动类型

即使使用,为序列化类型维护一个单独的DTO程序集可能是最方便的,但它并没有强制您这样做。最终,由于这些序列化器都很乐意跨操作系统/跨版本/跨语言/跨cpu工作,"不同的程序集"的事实非常"meh, whatever"。

关键提示:BinaryFormatter可能是脆性的。除了运行中的数据(例如,在两个AppDomain实例之间进行远程操作)之外,我从不推荐使用它。我当然不会将它用于任何持久化时间长度的东西,因为我不能保证将来能够重新加载它。

我现在是这样做的

    public sealed class VersionDeserializer : SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            var assemVer1 = Assembly.GetExecutingAssembly().FullName;
            var deserializeType = Type.GetType(string.Format("{0}, {1}", typeName, assemVer1));
            return deserializeType;
        }
    }
    private object FromByteArray(byte[] data)
    {
        var bf = new BinaryFormatter
        {
            Binder = new VersionDeserializer()
        };
        using (MemoryStream ms = new MemoryStream(data))
        {
            return bf.Deserialize(ms);
        }
    }