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