Protobuf-net对象图参考完整性



在protobuf-net版本2中有一个简洁的选项叫做[ProtoMember(2,AsReference=true)]。在大多数情况下,这是以下问题的后续问题:

  • protobuf-net序列化对象图

我开始怀疑是否总是保持引用完整性,而不管何时序列化/反序列化发生。当您使用AsReference选项时,protobuf-net是否已经这样做了?

我将一个基本的代码示例拼凑在一起用于说明目的,然后想,"也许我需要从ORM世界中借用一些想法?"我应该实现一个身份映射吗?我应该告诉protobuf(通过委托?)解析对外键值的引用吗?

我希望听到的答案是,protobuf-net可以在某种程度上保持跨汇编边界的引用完整性,即使是看起来相似的类型。

然而,这里有一个可供选择的序列,以防万一:

  • a => 1。解析对主键int的引用。序列化

  • b => 3。反序列化,4。解析主键为

Notes/约束:

  • 类是彼此的镜像,但在每个程序集中重新编译。

  • 对象图需要是相同的,无论对象何时被序列化。即a.f ref=B(序列化/反序列化)。C.ref=B (serialize/deserialize).

讨论示例:

using System;
using System.Collections.Generic;
using ProtoBuf;
namespace protobuf_question
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new A() { key = 1 };
            var b = new B() { A = a, key = 2 };
        }
    }
    [ProtoContract]
    public class A
    {
        [ProtoMember(1)]
        public int key { get; set; }
    }
    [ProtoContract]
    public class B
    {
        [ProtoMember(1)]
        public int key { get; set; }
        [ProtoMember(2,AsReference=true)]
        public A A { get; set; }  // a reference
    }
    [ProtoContract]
    public class IdentityMap<T,TKey>
    {        
        public static readonly IdentityMap<T,TKey> instance = new IdentityMap<T,TKey>();  // singleton
        private Dictionary<string, T> identitySpace { get; set; }
        public IEnumerable<string> GetIdentitySet (/* some criteria */)
        {            
            // used for serializing with reference safety between assemblies.
            throw new NotImplementedException();
        }
        public TKey GetKey(T reference)
        {
            // map object reference to identity map; return identity.
            throw new KeyNotFoundException();
        }
    }
}

我希望听到的答案是,protobuf-net可以在某种程度上保持跨汇编边界的引用完整性,即使是看起来相似的类型。

是的,它可以。当使用AsReference=true时,它在内部生成一个与其他任何无关的不透明键,并在网络上使用它;此键基于流的确定性特性。一切都是100%基于合同的。只要合约是兼容的,不管是相同的类型,相同的进程,相同的机器,相同的操作系统,等等。

唯一的例外是当使用DynamicType=true选项时,它将类型元数据刻录到网络中,但是即使是也不需要是实际的类型数据—如果您想提供比默认(type.AssemblyQualifiedName)更细粒度和可控的东西,您可以订阅一个事件。如果您使用 DynamicType,这将允许您透明地在实现之间交换类型。当然,如果你没有使用DynamicType,那么这个问题就不存在了。

你的身份映射…我不清楚他们的动机。但是需要明确的是:现有的代码并没有试图识别任何"主键"候选并仅仅序列化它们;它在第一次看到对象时序列化它(并且创建一个键),否则它只写入它上次组成的键。

最新更新