Protobuf-net对象图参考完整性

时间:2011-07-06 09:57:02

标签: protobuf-net

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

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

为了说明的目的,我把一个基本的代码示例汇总在一起,然后想,“也许我需要从ORM世界借用一些想法?”我应该实施身份地图吗?我应该以某种方式告诉protobuf(通过代理?)来解析对外键值的引用。

我想听到的答案是,protobuf-net可以在整个装配边界保持参考完整性,即使是看起来彼此相似的类型。

但是,这是一个替代的顺序:

  • a => 1.解析对主键int的引用,2。serialize

  • b => 3.反序列化,4。将主键int解析为引用

注释/限制条件:

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

  • 无论对象何时被序列化,对象图都需要相同。即A.ref = B(序列化/反序列化)。 C.ref = B(序列化/反序列化)。

讨论示例:

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();
        }
    }

}

1 个答案:

答案 0 :(得分:6)

  

我想听到的答案是,protobuf-net可以在整个装配边界保持参考完整性,即使是看起来彼此相似的类型。

是的,它可以。使用AsReference=true时,它会在内部生成与其他任何内容无关的不透明密钥,并在线路上使用它;此密钥基于流的确定性。一切都依旧100%合同。只要合同兼容,无论是相同类型,相同流程,相同机器,相同操作系统等都无关紧要。

唯一的例外是当使用DynamicType=true选项时,它会将类型元数据刻录到线路中,但即使也不需要实际类型数据 - 如果要提供比默认值(type.AssemblyQualifiedName)更精细和受控的内容,则可以订阅一个事件。如果使用 DynamicType,这将允许您在实现之间透明地交换类型。当然,如果使用DynamicType,则首先不存在此问题。


重新制作你的身份地图......我不清楚那里的动机。但要明确:现有代码不会尝试识别任何“主键”候选者并仅序列化那些;它在第一次看到它时序列化了对象(并且发明了一个键),否则它只是写了上次组成的键。