¿Qué atributo del ProtoInclude significar (en protobuf-net)
-
09-09-2019 - |
Pregunta
En el protobuf-Net aplicación , lo que hace el ProtoInclude atribuir significa, y lo que hace?
Un ejemplo sería apreciada.
en este post y no estoy seguro de lo lo hace. El ejemplo fue:
[Serializable,
ProtoContract,
ProtoInclude(50, typeof(BeginRequest))]
abstract internal class BaseMessage
{
[ProtoMember(1)]
abstract public UInt16 messageType { get; }
}
[Serializable,
ProtoContract]
internal class BeginRequest : BaseMessage
{
[ProtoMember(1)]
public override UInt16 messageType
{
get { return 1; }
}
}
Además, ¿hay una manera de generar tales herencia mediante el Protogen herramienta?
Solución
Lo siento, no fue mi intención faltar éste -. Por desgracia, no lo veo todo
Teniendo en cuenta las características específicas de la pregunta, voy a asumir que son al menos de pasada familiarizado con .proto; corrígeme si estoy equivocado.
[ProtoInclude]
funciona muy parecido a [XmlInclude]
para XmlSerializer
- o [KnownType]
para DataContractSerializer
- que le permite reconocer las subclases de un tipo en (de) la serialización. La única cosa adicional es que se necesita una etiqueta (número) para identificar cada subtipo (que debe ser único, y no entrar en conflicto con cualquiera de los campos de tipo matriz).
Re Protogen: nope; la especificación subyacente (por Google) no prevé la herencia en absoluto , por lo Protogen (a través de .proto) no tiene ningún mecanismo para expresar esto. protobuf-net ofrece soporte de herencia como un extensión , pero lo hace de una manera que todavía deja los mensajes de cable compatible con las otras implementaciones. En un impulso, tal vez Me podría añadir soporte Protogen a través de las nuevas propiedades de extensión en la especificación de Google, pero no lo han hecho todavía.
Por lo tanto; mirar el ejemplo; que expresa una relación de herencia entre BaseMessage
y BeginRequest
; independientemente de si lo haces:
Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
- cualquier manera, se iniciará en la base (
BaseMessage
) y trabajar hacia arriba; que no es exactamente cierto - escribe los datos de a partir deBeginRequest
(para que sepa que tenemos unBeginRequest
tan pronto como sea posible durante la deserialización). Lo importante es que los campos de cualquier tipo de contrato de los padres está incluido, y el serializador se ve en la real objeto pasado en -. No sólo el tipo que decir es
Asimismo, durante deserilaization, independientemente de si utiliza:
Deserialize<BaseMessage>(...)
Deserialize<BeginRequest>(...)
obtendrá el tipo que realmente serializado (presumiblemente un BeginRequest
).
Bajo el capó, por motivos de compatibilidad (con la amplia especificación de búferes de protocolo), esto es similar a escribir algo así como (valga cualquier error, mi .proto es oxidado):
message BaseMessage {
optional BeginRequest beginRequest = 50;
optional uint32 messageType = 1;
}
message BeginRequest {
}
(la anulación probablemente no debería especificar [ProtoMember]
, por cierto.
Normalmente, se escribiría campos en orden etiqueta ascendente, pero para hacer para una eficiente deserialización el motor descaradamente elige para escribir los datos de subclase primero (que está explícitamente permitido por la especificación) - es decir, se escribe algo así como (que tendrá que imaginar el binario ...):
[tag 50, string][length of sub-message][body of sub-message][tag 1, int][value]
(en este caso, el cuerpo de la sub-mensaje está vacío)
¿Eso lo cubren?