使用 FSPickler 将二进制反序列化为另一种类型

binary deserialization to another type with FSPickler

我有一个类型:

type T = 
    {
        a: int
        b: string
    }

和一个名为 'myArray' 的 T 类型数组。

我想用 FSPickler 序列化 myArray:

FsPickler.CreateBinarySerializer().Pickle myArray

但是在 pickle 文件中,类型 T 是完全合格的,如果我将它重新定位到另一个 app/namespace,那么 unpickle 就会失败。

我在 FSPickler git 上询问过,但我收到的答案是:

Per documentation in http://mbraceproject.github.io/FsPickler/ the serializer is not > designed with version tolerance in mind. That being said, it should be possible to work > around that issue by providing a custom implementation of the ITypeNameConverter interface.

好的,很公平。

但是,该文档提供的示例清楚地由了解 picklers 的人编写,并且适用于也了解 picklers 的其他人。

谁能post举个例子,我可以为这个基本案例制作自定义序列化器/反序列化器?从文档中,我看到所有奇怪的情况都是在假设 reader 知道如何使用 FSPickler 制作基本序列化程序的情况下解释的。

或者,也许我在文档中漏掉了一些非常明显的东西,如果我看到它,我会很高兴地认出它:)

文档在这里:https://mbraceproject.github.io/FsPickler/tutorial.html

而且,对于上下文,我正在处理 24 GB 的数据(显然比这个例子中的类型更复杂),所以速度就是一切,而 FSPickler 看起来相当快。

似乎根本没有关于此的任何文档,但我设法拼凑出了一些有用的东西。我发现的技巧是使用一个非常简单的转换器,它始终使用相同的类型名称,如下所示:

let converter =
    {
        new ITypeNameConverter with
            member this.OfSerializedType(typeInfo) =
                { typeInfo with Name = "dummy" }   // always use dummy type name
            member this.ToDeserializedType(typeInfo) =
                typeInfo
    }

然后我们可以像这样腌制 T 的数组:

type T = 
    {
        a: int
        b: string
    }

let tArray =
    [|
        { a = 1; b = "one" }
        { a = 2; b = "two" }
        { a = 3; b = "three" }
    |]

let serializer = FsPickler.CreateBinarySerializer(typeConverter = converter)
let bytes = serializer.Pickle(tArray)

然后我们可以将它分解为具有相同结构的不同类型的数组(“duck typing”):

type U =
    {
        a: int
        b: string
    }

let uArray = serializer.UnPickle<U[]>(bytes)

我不知道这是否是“正确”的做法。我发现 ITypeNameConverter 的行为并不像我预期的那样。特别是,似乎 OfSerializedType 在 pickling 和 unpickling 期间都被调用,而 ToDeserializedType 根本没有被调用。也许我遗漏了一些重要的东西。