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();
}
}
}
答案 0 :(得分:6)
我想听到的答案是,protobuf-net可以在整个装配边界保持参考完整性,即使是看起来彼此相似的类型。
是的,它可以。使用AsReference=true
时,它会在内部生成与其他任何内容无关的不透明密钥,并在线路上使用它;此密钥基于流的确定性。一切都依旧100%合同。只要合同兼容,无论是相同类型,相同流程,相同机器,相同操作系统等都无关紧要。
唯一的例外是当使用DynamicType=true
选项时,它会将类型元数据刻录到线路中,但即使也不需要实际类型数据 - 如果要提供比默认值(type.AssemblyQualifiedName
)更精细和受控的内容,则可以订阅一个事件。如果使用 DynamicType
,这将允许您在实现之间透明地交换类型。当然,如果不使用DynamicType
,则首先不存在此问题。
重新制作你的身份地图......我不清楚那里的动机。但要明确:现有代码不会尝试识别任何“主键”候选者并仅序列化那些;它在第一次看到它时序列化了对象(并且发明了一个键),否则它只是写了上次组成的键。