2009-07-02 14 views
4

クラスを考えるのサイズ:WCF - おおよそのメッセージを測定することは、プログラム

[DataContract] 
public sealed class ChangedField 
{ 
    [DataMember(Name="I")] public ushort FieldId { get; set; } 
    [DataMember(Name="V")] public object Value { get; set; } 
} 

WireSharkのバインディングWCF TCPを経由して送信されたときに、メッセージのエンコーディングはバイナリのみ(印刷可能な文字である、ことを示しているが、あなたが得ますアイデア):

ChangedFielda.I..a.V....e:double..e http://www.w3.org/2001/XMLSchema.s.....a.

しかし、私はそう...

0123のように、この型のインスタンスをシリアライズ場合
var ser = new DataContractSerializer(typeof(ChangedField)); 
var stream = new MemoryStream(); 
ser.WriteObject(stream, new ChangedField { FieldId = 1, Value = 1.23d }); 

...その後ストリームは、このに似ているSOAPのXMLが含まれています

<ChangedField> 
    <I>1</I> 
    <V i:type="a:double" xmlns:a="http://www.w3.org/2001/XMLSchema">1.23</V> 
</ChangedField> 

だから私の質問は、私は自分のコードでこのバイナリ表現を生成するためにDataContractSerializerを制御することができますどのようにのですか?余談として

:あなたが見ることができるように、メッセージはobjectプロパティは、その型をエンコードしている必要がありますという事実(それゆえURI)によって肥大化している

。私はこのシナリオのようにフィールドIDがタイプ(この場合はdouble)を決定するので、カスタムバイナリエンコーディングを使用するようにこれを変更します。

答えて

3

TCPバインディングは、デフォルトでバイナリメッセージエンコーダを使用します。ここで、2番目の例では、データコントラクトをXMLにシリアル化するだけです。バイナリメッセージエンコーダでは、基本的に、XMLの代わりに独自のバイナリ形式を生成するカスタムXmlWriter実装でデータコントラクトシリアライザを提供しています。

これを別のバインディング(HTTPなど)で使用する場合は、代わりにカスタムバインディングを作成し、通常のTextMessageEncodingElementの代わりにBinaryMessageEncodingElement要素を追加する必要があります。

+0

ありがとう、tomasr。私はバインディングを変更したくありません。私がしたいのは、メッセージサイズの違いを証明するいくつかのテストケースを作成することですが、毎回WireSharkでスヌープしたくありません。 –

+0

Drew:これも可能です。私はここでそれを行う方法を示すサンプルアプリケーションを投稿しました:http://winterdom.com/2009/07/comparing-text-and-binary-serialization-in-wcf – tomasr

+0

ああ、それは私のように見える後に。私は明日仕事でそれを試してみて、あなたに戻ってきます。どうもありがとう! –

0

DataContractSerializerのドキュメントを読んでいますか?

最初 の書き込みまたはフォーマットを読み取るにクラス 、オブジェクトの適切なインスタンスを作成DataContractSerializer、 を使用します。たとえば、XmlDictionaryWriterの インスタンスです。 次に、WriteObjectメソッドを呼び出して にデータを保存します。データを取得するには、 (XML ドキュメントの場合は XmlDictionaryReaderなど)を読み取り、ReadObject メソッドを呼び出すのに適したオブジェクトを作成します。

あなたは約XmlDictionaryWriterについて読んでみたいです。

+1

@ジョン - XmlDictionaryWriterがどのように役立つかわかりません。それは多くの抽象メンバを持つ抽象型であり、フレームワーク内でそれを公開する実装は見つかりませんでした。あなたは詳しく説明できますか? –

1

DataContractSerializerを制御することはできませんが、テキスト形式またはバイナリ形式にシリアル化するかどうかに関係なく、WCFバインディングを制御できます。

あなたが気づいたように、NetTcpBindingはデフォルトでバイナリになっており、コンパクトで高速です。 Httpベースのバインディングは、相互運用性のためにデフォルトでTextに設定されているため、より冗長でパフォーマンスが低下します。

しかし、独自のバイナリベースのHTTPバインディングの作成を妨げるものは何もありません。IF外部クライアントとの相互運用性については、受け入れることを喜んで受け入れています。これは、同じカスタムバインドを使用する独自の内部クライアントでのみ機能します。

基本的には、独自のカスタムバインディングを最初からビルドする必要があります(コードまたは設定で)。コンフィグではそれは非常に簡単です:

<system.serviceModel> 
    <bindings> 
    <customBinding name="binaryHttpBinding"> 
     <binaryMessageEncoding /> 
     <httpTransport /> 
    </customBinding> 
    </bindings> 
</system.serviceModel> 

あなたは必見指定する2つの最小の部分は、メッセージのエンコードやトランスポートプロトコルです - 何かは任意です。

彼らは結合この新しい、カスタムバイナリオーバーHTTPを使用しますように、今、あなたのWCFサービスとクライアントを指定することができます。

<system.serviceModel> 
    <services> 
     <service name="YourService"> 
     <endpoint address="http://whatever.com:8888/YourAddress" 
        binding=binaryHttpBinding" 
        contract="IYourContract" /> 
     </service> 
    </services> 
</system.serviceModel> 

(と同じことがまた<client>でクライアントのために働きますもちろん、セクション)。

あなたはそれを持っています - あなたのコードの中で、形や形を問わずDataContractSerializerを制御することではなく、カスタムバインディングを作成して使用するだけです。

マルク・

EDIT(コメントの後左):
まあ、WCFは確かに非常に拡張性があるので、あなたは、クライアントのうち途中でこのようなメッセージの検査官を行うことができます。あなたは何もしません(IClientMessageInspector由来)などのメッセージインスペクタを書きますが、メッセージを検査し、その大きさを測定して、ファイルやデータベースここ

+0

ありがとうMarcこの答えです。面白いですが、私が求めているものではありません。NetTcpBindingが使用するバイナリフォーマットを使用して特定のオブジェクトに対して送信されるバイト数を測定するだけですが、コードから取得します。私はon-the-wireのサイズを減らすために取り組んでいます。クライアント/サーバーとパケットスニッファを使用するよりも小さなアプリケーションや単体テストでこれを行うほうが簡単です。 –

0

にそれを書き出すことができ、私が問題に見つけることができる最も簡単な解決策は以下のとおりです。

new TextMessageEncodingBindingElement() 

...か...

new BinaryMessageEncodingBindingElement() 
0123: encodingパラメータはどちらかである
static byte[] Serialise(object obj, MessageEncodingBindingElement encoding) 
{ 
    encoding.MessageVersion = MessageVersion.Soap12; 
    var stream = new MemoryStream(); 
    var message = Message.CreateMessage(MessageVersion.Soap12, "", obj, 
     new DataContractSerializer(obj.GetType())); 
    encoding.CreateMessageEncoderFactory().Encoder.WriteMessage(message, stream); 
    return stream.ToArray(); 
} 

...

...テキスト形式でもバイナリ形式でもかまいません。

link to his article on this topicの場合、tomasrに感謝します。

+1

メッセージインスペクタと一緒に使用しますか?私は、あなたはその方法をどこにつけますか? – dragonfly

関連する問題