repeated字段表明传输0~N个数据对象。当传输的数据对象个数大于0时,接收方能够按照覆盖的方式,使用新的数据,替换以前的全部数据。可是,当传输的数据对象个数等于0的时候,接收方如何意会发送方的意图呢?是保留不变仍是删除列表? java
解决办法:影子字段,为每一个repeated type name = i;增长一个include影子字段, optional bool include_name = i+1; 当 include_name 的值为true时,表示须要修改内容,当include_name为false时,接收方忽略name字段。 c#
repeated字段每次传输的是一个列表的全部对象的数据。列表的内容改变时,特别是有时候真是新增或者减小几个数据对象时,依旧须要传输整个完整的列表数据。这在数据量比较少的时候不成问题,可是若是列表的成员为成千上万个的时候,恐怕使用单一的repeated字段是没法知足的。在此时最好是repeated字段只传输那些变更的数据对象,例如值传输全部新增的,或者值传输全部被删除的。 数据结构
解决办法:所以再次最好增长一个枚举和一个字段。 工具
enum RepteateFieldOpType { add = 0; del = 1; replace = 3;} ui
optional RepteateFieldOpType op_name = i+2 [ default = replace]; spa
protoc.exe代码生成器生成的消息对象不但引用了protobuf库的基础消息,并且还添加了不少额外的字段。生成的消息类没法直接用在工程的业务逻辑对象中。 设计
所以,须要在工程中,重复定义一套业务对象,数据结构和protobuf 的message对象至关。而且在业务对象和消息对象之间进行数据的赋值。 指针
解决办法:工程中,涉及到和业务逻辑对象相关的消息,最好采用自动化工具从class对象中提取字段,而且映射为消息。并使用工具自动生成class对象和protobuf 消息对象之间的负值,如toMessage和fromeMessage等方法。 对象
普通数据类型单一,可使用最大化的方式解决。而复杂数据,protobuf只有一种模式,message。对于java,c#语言来讲,能够认为是引用。可是对于C++语言来讲,是映射为指针对象呢?仍是普通的复合对象成员呢?通常状况下能够根据optional或者required来关联。复合对象使用required字段,指针对象使用optional字段。另外repeated表明的是一个列表,repeated message,是值对象的列表仍是值引用(指针)的列表,这个也很差区分。 map(字典)也不能直接映射到protobuf. 继承
以C++为例的解决方案:
对于C++ class中的普通数据成员,直接映射为protobuf的相应的数据成员。
对于C++class,映射为一个 message
对于 C++ class中的普通复合成员,直接映射为 required message便可。
对于C++ class中的指针复合成员,直接映射为optional message便可。既然是指针,那么传输的对象若是是整个类,和普通的复合成员也就没有多大的区别。可是若是此类设计到继承时,传输的时候能够只传输基类的内容,使得接收方能够根据基类的相关信息找到业务对象,而不是重新建立一个业务对象。所以还须要为每一个指针复合成员定义一个find方法,用于把消息中的值,映射为业务对象。
C++,Java,C++的类都不多是无父类的,在一个稍微复杂点的系统,业务对象都有本身的继承体系的。而protobuf的message和C的struct同样,是没有结构的概念的。
如何把C++中的继承体系映射到protobufmessage中,能够借鉴一下C的struct的作法。
有1中方式。第一种是分散式的,每一个继承的子类都使用一个独立的消息,在消息中的第一个字段为父类的消息,而且名称固定为base。例如
Class A {}; Class B : public {}
message B {
required A base = 1;
.....
}
在多继承模式下,我的无能为力,那位有更好的 !!
另一种方式是集中式,整个继承体系使用一个独立的类,把全部的子类都封装在一块儿,使用起来相似于C中的union。
例如
Class A ;
Class B : public A;
class C : public A;
message XX {
required message A a =1;
optional message B b = 2;
optional message C c = 3;
}