Présentation de Protocol Buffers

Protocol Buffers est un système de sérialisation pour des données structurées développé par Google. Il est indépendant du point de vue langage de programmation et du point de vue plateforme.

Google dit à ce propos : « Pensez XML, mais plus petit, plus rapide et plus simple »

Vous définissez comment vous souhaitez que vos données soient structurées une seule fois, puis vous pouvez utiliser des codes sources générés pour facilement lire et écrire les données depuis et vers une variété de flux de données avec divers langages.

Utilisation de Protocol Buffers

L’utilisation de Protocol Buffers se fait en 3 étapes :

  • Création de fichiers proto,
  • Génération des classes à partir des fichiers proto,
  • Configuration des services WCF pour utiliser la sérialisation Protocol Buffers.

Création des fichiers proto

Les fichiers proto sont des fichiers texte contenant la définition des classes à générer. Voici un exemple de fichier proto (Person.proto) :

package SampleProject;
message Person
{
    required string FirstName = 1;
    required string LastName = 2;
}

“package” donnera après la génération le namespace en C# et “message” donnera la classe Person contenant les éléments défini.

Les fichiers proto doivent être encodé en US-ASCII – Codepage 20127 pour pouvoir utiliser protogen.

Génération des classes

Après avoir créé les fichiers proto il faut maintenant générer les classes C#. Pour cela un outil nommé protogen.

Voici la commande générant la classe Person :

protogen.exe –i:Person.proto –o:Person.cs –t:csharp.xslt
  • -i: indique le fichier d’entrée (ici Person.proto),
  • -o: indique le fichier de sortie à créer (ici Person.cs),
  • -t: indique le fichier de transformation (ici celui pour C#).

Ci dessous la classe générée par la commande précédente (Person.cs) :

using System;
using Protobuf;

namespace SampleProject
{
    [Serializable]
    [ProtoContract(Name=@"Person")]
    public partial class Person : IExtensible
    {
        public Person()
        {

        }
        
        private string_FirstName;
        
        [ProtoMember(1, IsRequired = true, Name=@"FirstName", DataFormat = DataFormat.Default)]
        public stringFirstName
        {
            get
            {
                return _FirstName;
            }
            set
            {
                _FirstName = value;
            }
        }

        private string_LastName;
        
        [ProtoMember(2, IsRequired = true, Name=@"LastName", DataFormat = DataFormat.Default)]
        public stringLastName
        {
            get
            {
                return _LastName;
            }
            set
            {
                _LastName = value;
            }
        }
        
        private IExtension extensionObject;
        
        IExtension IExtensible.GetExtensionObject(bool createIfMissing)
        {
            return Extensible.GetExtensionObject(refextensionObject, createIfMissing);
        }
    }
}

Il suffit d’inclure le ou les fichier(s) généré(s)dans le projet pour les utiliser.

Configuration du service WCF

Serveur WCF

La configuration se fait en deux parties :

  • Ajout de protobuf-net dans les références du projet via nuget,
  • Configuration du projet pour son utilisation.

L’utilisation de protobuf-net par le service WCF s’effectue par la configuration via App.config/Web.config du service.

Dans la partie :

<system.serviceModel>
...
</system.serviceModel>

Il faut d’abord définir l’extension protobuf ainsi en prenant soin de renseigner le bon numéro de version du fichier (par exemple 2.0.0.621 à l’heure où j’écris ces lignes) :

<extensions>
    <behaviorExtensions>
        <add
            name="protobuf"
            type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/>
    </behaviorExtensions>
</extensions>

Puis toujours dans App.config/Web.config, nous définissons le endpointBehavior pour qu’il utilise notre extension protobuf :

<behaviors>
    <endpointBehaviors>
        <behavior name="protoEndpointBehavior">
            <protobuf />
        </behavior>
    </endpointBehaviors>
</behaviors>

Enfin dans la définition du endpoint nous rajoutons l’attribut behaviorConfiguration qui pointera sur notre endpointBehavior :

<endpoint
    address=""
    binding="wsHttpBinding"
    contract="DataTransferObjectLibrary.IService"
    behaviorConfiguration="protoEndpointBehavior">
    <identity>
        <dns value="localhost"/>
    </identity>
</endpoint>

Maintenant il suffit juste d’utiliser les classes générées par protogen pour les transférer via le service WCF.

Client WCF

La configuration côté client est presque identique. Dans app.config (cas d’un client lourd) nous retrouvons les mêmes éléments :

  • Ajout de protobuf-net dans les références du projet via nuget,
  • Configuration du projet pour son utilisation.

Dans la configuration app.config nous retrouvons les éléments suivant dans la partie system.serviceModel :

  • La définition de l’extension :
<extensions>
    <behaviorExtensions>
        <add
            name="protobuf"
            type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/>
    </behaviorExtensions>
</extensions>
  • La définition du endpointBehavior :
<behaviors>
    <endpointBehaviors>
        <behavior name="protoEndpointBehavior">
            <protobuf/>
        </behavior>
    </endpointBehaviors>
</behaviors>
  • L’ajout de l’attibut behaviorConfiguration à la définition du endpoint :
<endpoint
    address="http://localhost:22870/PersonService.svc"
    binding="wsHttpBinding"
    bindingConfiguration="WSHttpBinding_IService"
    contract="ServiceReference.IService"
    name="WSHttpBinding_IService"
    behaviorConfiguration="protoEndpointBehavior">
    <identity>
        <dns value="localhost"/>
    </identity>
</endpoint>