あるプラットフォームでシリアル化したものを別のプラットフォームで逆シリアル化できますか?
はい、いいえ。 Protobufでは、答えが「はい」の単純なデータ型について説明していますが、残念ながら、答えが「いいえ」のデータ型もあります。 そして、私たちの例はそれを証明しています! DateTimeのタイプに注意してください。 それ自体は複雑なデータ型であり、プラットフォームに依存しています。 したがって、シリアル化した場合、すべてが別のプラットフォームで復元されるという保証はありません。 したがって、この欠点を解消する方法を考え出す必要があります。 ソリューションの1つはprotobuf-netで既に実装されており、次のとおりです。DateTime型は、1970年1月1日(UNIXシステムの参照ポイント)から経過した時間間隔としてシリアル化されます。 残りのタイプのコンベンションはここにあります 。
このような状況から身を守るために、拡張子が.protoのファイルを使用してデータ構造を記述することをお勧めします(Visual Studioとの統合がサポートされています)。 これは、ソースコード生成プログラムが最終的なプログラミング言語の機能を考慮して、構造化データの移植可能な表現を取得するのに役立ちます。 この場合、次の説明があります(この例では、DateTime型は、 この説明に基づいて独自のデータ型に対応しています)。
package Proto.Common;
message Task
{
optional int32 Id = 1;
optional DateTime CreatedAt = 2;
optional string CreatedBy = 3;
enum TaskPriority
{
Low = 0;
Medium = 1;
High = 2;
}
optional TaskPriority Priority = 4;
optional string Content = 5;
}
* This source code was highlighted with Source Code Highlighter .
なぜなら 生成されたコードは十分に大きく、手動での編集を目的としていないため、省略します。
サポートされているJavascript言語のリストで気づいたのですが、protobufを優先してJSONを放棄する価値はありますか?
絶対にありません。 JSONにはすべてのブラウザーにサポートが組み込まれているため、クライアントに対してスクリプトをシリアル化および非シリアル化するためにスクリプトをダウンロードする必要はありません。 データ量に問題がある場合は、たとえば圧縮を有効にしてみてください。 ただし、この実装は、たとえばNodeJSでサーバー側のJavaScriptを使用して開発している場合に間違いなく役立ちます。
上記の例以外のprotobufはどこで使用できますか?
.Net開発者として、Silverlight、Compact Framework、Monoなどのプラットフォームのprotobuf-netサポートがあります。 protobufをWCFに統合するのがどれほど簡単かを見てみましょう。 伝統的に私たちの本質の説明から始めましょう(TaskPriorityについては何も変わっていません):
using System;
using System.Runtime.Serialization;
namespace Proto.Common
{
[DataContract]
public class Task
{
[DataMember(Order = 1)]
public int Id { get ; set ; }
[DataMember(Order = 2)]
public DateTime CreatedAt { get ; set ; }
[DataMember(Order = 3)]
public string CreatedBy { get ; set ; }
[DataMember(Order = 4)]
public TaskPriority Priority { get ; set ; }
[DataMember(Order = 5)]
public string Content { get ; set ; }
}
}
* This source code was highlighted with Source Code Highlighter .
ご覧のとおり、前の説明とほとんど違いはありません。 しかし、正直に言うと、protobufを使用した例のようには見えません。 サービス契約:
using System.ServiceModel;
namespace Proto.Common
{
[ServiceContract]
public interface ITaskManager
{
[OperationContract]
Task[] GetTasks();
}
}
* This source code was highlighted with Source Code Highlighter .
再びprotobufのヒントではありません。 あなたができる唯一の言及はサービス構成ファイルです:
<? xml version ="1.0" ? >
< configuration >
< system.serviceModel >
< services >
< service name ="Proto.Server.TaskManager"
behaviorConfiguration ="Proto.Server.ServiceBehavior" >
<!-- Service Endpoints -->
< endpoint name ="Proto.Server.Endpoint"
address ="net.tcp:\\localhost:9000"
binding ="netTcpBinding"
contract ="Proto.Common.ITaskManager"
behaviorConfiguration ="Proto.Common.EndpointBehavior" />
</ service >
</ services >
< behaviors >
< serviceBehaviors >
< behavior name ="Proto.Server.ServiceBehavior" >
<!-- To receive exception details in faults for debugging purposes, set the value below to true.
Set to false before deployment to avoid disclosing exception information -->
< serviceDebug includeExceptionDetailInFaults ="true" />
</ behavior >
</ serviceBehaviors >
< endpointBehaviors >
< behavior name ="Proto.Common.EndpointBehavior" >
< protobuf />
</ behavior >
</ endpointBehaviors >
</ behaviors >
< extensions >
< behaviorExtensions >
< add name ="protobuf"
type ="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=1.0.0.280, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
</ behaviorExtensions >
</ extensions >
</ system.serviceModel >
</ configuration >
* This source code was highlighted with Source Code Highlighter .
そして顧客:
<? xml version ="1.0" ? >
< configuration >
< system.serviceModel >
< client >
< endpoint name ="Proto.Client.Endpoint"
address ="net.tcp:\\localhost:9000"
binding ="netTcpBinding"
contract ="Proto.Common.ITaskManager"
behaviorConfiguration ="Proto.Common.EndpointBehavior" />
</ client >
< behaviors >
< endpointBehaviors >
< behavior name ="Proto.Common.EndpointBehavior" >
< protobuf />
</ behavior >
</ endpointBehaviors >
</ behaviors >
< extensions >
< behaviorExtensions >
< add name ="protobuf"
type ="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=1.0.0.280, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
</ behaviorExtensions >
</ extensions >
</ system.serviceModel >
</ configuration >
* This source code was highlighted with Source Code Highlighter .
クライアントとサービスの実装は簡単で、興味の対象ではありません。
メッセージロギングを有効にすると、次のログエントリが表示されます。
< MessageLogTraceRecord Time ="2011-05-12T16:17:03.2780000+04:00" Source ="TransportSend" Type ="System.ServiceModel.Dispatcher.OperationFormatter+OperationFormatterMessage" xmlns ="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace" >
< s:Envelope xmlns:s ="http://www.w3.org/2003/05/soap-envelope" xmlns:a ="http://www.w3.org/2005/08/addressing" >
< s:Header >
< a:Action s:mustUnderstand ="1" >
tempuri.org/ITaskManager/GetTasksResponse
</ a:Action >
< a:RelatesTo >
urn:uuid:768e2f40-612c-4593-8cfb-eacb7b291a9c
</ a:RelatesTo >
< a:To s:mustUnderstand ="1" >
www.w3.org/2005/08/addressing/anonymous
</ a:To >
</ s:Header >
< s:Body >
< GetTasksResponse xmlns ="http://tempuri.org/" >
< proto >
Ci4IARIJCPTs+c/8SxAEGgpTdGV2ZSBKb2JzIAIqEUludmVudCBuZXcgaVBob25lCi8IAhIJCPTclY/4SxAEGg1TdGV2ZSBCYWxsbWVyKhFJbnN0YWxsIG93biBTa3lwZQ==
</ proto >
</ GetTasksResponse >
</ s:Body >
</ s:Envelope >
</ MessageLogTraceRecord >
* This source code was highlighted with Source Code Highlighter .
私が覚えている限り-データコントラクトの使用は属性に限定されませんが、これらのコントラクトの拡張はどうですか?
WCFのように。 IExtensibleDataObjectを使用して、契約の変更を説明できることを知っています。 Protobuf-netには同様のインターフェースがあり、IExtensibleと呼ばれます。 違いはそれほど大きくないので、 ここで自分で調べることができます 。
多くの開発者がWCFでprotobuf-netの使用を拒否するのはなぜですか?
これは単なる神話にすぎません。 開発者は通常、ネットワーク共有を高速化するソリューションを探しているときにprotobufを見つけるだけです。 それらのいくつかはさらに進んで、WCFによって課される抽象化のレベルを削除し、たとえばTcpClientを使用して最高速度を実現します。 この場合は、 Thriftの方が便利かもしれません。
あなたは私を納得させました。 私は間違いなく次のプロジェクトでprotobuf-netを試します。 議論してくれてありがとう!
お願いします。 このプロジェクトは活発に開発されているので、おそらく私たちはそれを複数回議論するでしょう。