読者です 読者をやめる 読者になる 読者になる

WCF で Protocol Buffers を使う方法

以前、.NET で Googleシリアライズツール ProtocolBuffers が使えるようになるライブラリ protobuf-net を紹介しました。

この protobuf-net は WCF 向けの機能も提供していて、ProtocolBuffers でシリアル化したデータを WCF の通信で使うことができます。使い方を簡単に説明すると、ProtoBehaviorAttribute を OperationContractAttribute と一緒に指定してやるだけ。

using System;
using System.ServiceModel;
using ProtoBuf;
using ProtoBuf.ServiceModel;

namespace WcfProtoBufSample
{
    // ProtocolBuffers でシリアル化するので
    // DataContract や DataMember ではなく、
    // 専用の属性を指定する
    [ProtoContract]
    public class Person
    {
        [ProtoMember(1)]
        public string Name { get; set; }
        [ProtoMember(2)]
        public int Age { get; set; }
    }

    [ServiceContract]
    public interface IPersonService
    {
        // ProtocolBuffers を使ってシリアル化するオペレーションに
        // ProtoBehaviorAttribute を付ける
        [ProtoBehavior]
        [OperationContract]
        void Echo(Person person);
    }

    public class PersonService : IPersonService
    {
        public void Echo(Person person)
        {
            // ProtocolBuffers を使ってシリアル化されたか確認するために
            // メッセージの中身も出力
            Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage);
            Console.WriteLine("{0}({1})", person.Name, person.Age);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string address = "net.pipe://localhost/Person";
            ServiceHost host = new ServiceHost(typeof(PersonService));
            host.AddServiceEndpoint(typeof(IPersonService),
                new NetNamedPipeBinding(),
                address);
            host.Open();

            IPersonService client = ChannelFactory<IPersonService>.CreateChannel(
                new NetNamedPipeBinding(),
                new EndpointAddress(address));
            client.Echo(new Person() { Name = "桂馬", Age = 17 });

            Console.ReadLine();
            ((IClientChannel)client).Close();
            host.Close();
        }
    }
}

ProtocolBuffers を使ってシリアル化されたか確認するために、Message の内容を出力しています。実行結果は下図の通り。
f:id:griefworker:20100728170732j:image

protobuf-net 配布サイトのドキュメントによると、DataContractSerializer や XmlSerializer よりも protobuf-net の方が、高速にシリアル化・逆シリアル化できるし、サイズも小さいそう。通信速度を追い求めるなら、WCF + ProtocolBuffers の組み合わせを検討するのもいいかもしれませんね。