Question

Dans le Protobuf-Net mise en œuvre , qu'est-ce que le ProtoInclude attribut signifie, et que fait-il?

Un exemple serait apprécié.

Je l'ai vu dans cette post et je ne suis pas sûr de ce que Cela fait. L'exemple était:

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

Aussi, est-il un moyen de générer un tel héritage en utilisant le Protogen outil?

Était-ce utile?

La solution

Désolé, je ne voulais pas manquer celui-ci -. Hélas, je ne vois pas tout

Compte tenu des spécificités de la question, je vais supposer que vous êtes au moins passagèrement familier avec .proto; corrigez-moi si je me trompe.

[ProtoInclude] fonctionne beaucoup comme [XmlInclude] pour XmlSerializer - ou [KnownType] pour DataContractSerializer - il permet de reconnaître les sous-classes d'un type pendant la sérialisation (de). La seule chose supplémentaire est qu'il a besoin d'une balise (nombre) pour identifier chaque sous-type de (qui doit être unique, et non en conflit avec l'un des champs de type parent).

Re Protogen: Non; la spécification sous-jacente (par Google) ne fait aucune provision pour héritage tout , si Protogen (via .proto) n'a pas de mécanisme pour exprimer. protobuf-net prend en charge l'héritage comme extension , mais il le fait d'une manière qui laisse encore le fil compatible avec les messages avec les autres implémentations. Lors d'une poussée, peut-être je pourrais ajouter le support Protogen via les nouvelles propriétés d'extension dans la spécification google, mais je n'ai pas encore fait.

; de regarder l'exemple; qui exprime une relation d'héritage entre BaseMessage et BeginRequest; indépendamment du fait que vous faites:

Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
  • De toute façon, il va commencer à la base (BaseMessage) et travailler vers le haut; qui n'est pas exactement true - il écrit les données en commençant par BeginRequest (pour qu'il sache que nous avons un BeginRequest le plus tôt possible lors de la désérialisation). L'important est que les champs de tous les types de contrat parent est inclus, et le sérialiseur regarde réelle objet passé -. Pas seulement le type que vous dire il est

De même, au cours deserilaization, que vous utilisez:

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

vous obtiendrez le type que vous avez réellement un numéro de série (probablement un BeginRequest).

Sous le capot, à des fins de compatibilité (avec la grande spécification des tampons de protocole), ce qui est similaire à écrire quelque chose comme (pardonnez toute erreur, mon .proto est rouillé):

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

(la dérogation ne devrait probablement pas spécifier [ProtoMember], btw.

Normalement, il écrirait des champs dans l'ordre de la balise ascendante, mais de faire pour l'efficacité désérialisation le moteur choisit effrontément pour écrire les données de sous-classe first (qui est explicitement autorisé par la spécification) - c.-à-il écrit quelque chose comme (vous devrez imaginer le binaire ...):

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

(dans ce cas, le corps du sous-message est vide)

Est-ce que le couvrir?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top