Pergunta

Na implementação do protobuf-net , o que faz o ProtoInclude atributo média, eo que ele faz?

Um exemplo seria apreciada.

eu vi neste post e eu não tenho certeza do que ele faz. O exemplo foi:

[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; }
    }
}

Além disso, existe uma maneira de gerar tal herança usando o protogen ferramenta?

Foi útil?

Solução

Desculpe, eu não queria perder este -., Infelizmente, eu não ver tudo

Dadas as especificidades da pergunta, eu vou assumir que você é, pelo menos passingly familiarizado com .proto; me corrija se eu estiver errado.

[ProtoInclude] funciona muito como [XmlInclude] para XmlSerializer - ou [KnownType] para DataContractSerializer - que lhe permite reconhecer subclasses de um tipo durante a (de) serialização. A única coisa adicional é que ele precisa de uma tag (número) para identificar cada sub-tipo (que deve ser único, e não colidir com qualquer um dos campos do tipo pai).

Re protogen: Não; a especificação subjacente (pelo Google) não prevê a herança em tudo , de modo protogen (via .proto) não tem nenhum mecanismo para expressar isso. protobuf-net oferece suporte a herança como um extensão , mas faz isso de uma forma que ainda deixa a mensagens fio compatível com as outras implementações. Em um impulso, talvez eu poderia adicionar suporte protogen via as novas propriedades de extensão no google spec, mas eu não fiz isso ainda.

Assim; a olhar para o exemplo; que exprime uma relação entre herança BaseMessage e BeginRequest; independentemente de você fazer:

Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
  • De qualquer maneira, ele vai começar na base (BaseMessage) e trabalhar para cima; o que não é exatamente true - escreve o dados começando com BeginRequest (para que ele saiba que temos um BeginRequest o mais cedo possível durante a desserialização). O importante é que os campos de quaisquer tipos de contrato pai está incluído, e os olhares serializador no real objeto passado -. Não apenas o tipo que você dizer é

Da mesma forma, durante deserilaization, independentemente de você usar:

Deserialize<BaseMessage>(...)
Deserialize<BeginRequest>(...)

você vai obter o tipo que você realmente serializado (presumivelmente um BeginRequest).

Sob o capô, para fins de compatibilidade (com a grande especificação buffers de protocolo), este é semelhante a escrever algo como (perdoe quaisquer erros, meu .proto está enferrujado):

message BaseMessage {
    optional BeginRequest beginRequest = 50;
    optional uint32 messageType = 1;   
}
message BeginRequest {        
}

(a substituição, provavelmente, não deve especificar [ProtoMember], btw.

Normalmente, ele escreveria campos em ordem crescente tag, mas para fazer para desserialização eficiente o motor cheekily escolhe para gravar os dados da subclasse início (o que é explicitamente permitido pela especificação) - ou seja, ele escreve algo como (você vai ter que imaginar o binário ...):

[tag 50, string][length of sub-message][body of sub-message][tag 1, int][value]

(neste caso, o corpo do sub-mensagem está vazia)

O que cobri-lo?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top