2009-08-24 18 views
5

私はWCFをかなり新しくしており、MessageContractの継承が正しく機能するようにする方法について質問があります。私のセットアップの簡略化されたバージョンは、 "基本"メッセージタイプ、そしてそれから継承する別の "テスト"メッセージです。WCF MessageContract継承

[MessageContract] 
public abstract class BaseMessage 
{ } 

[MessageContract] 
public class TestMessage : BaseMessage 
{ } 

私は、その後のように定義のServiceContractの非同期OperationContractを持っている:

[OperationContract(AsyncPattern = true)] 
IAsyncResult BeginFindRequest(BaseMessage request, AsyncCallback callback, object asyncState); 

私は取得しています問題は、BeginFindRequestメソッドを呼び出すときである、とリクエストパラメータにTestMessageインスタンスに渡しますWCFフレームワークは、TestMessageインスタンスをサービス/サーバー側のBaseMessageにdeserializeしています。これは抽象クラスとして定義されているとして、それは、次のエラーが発生:

"The message cannot be deserialized into MessageContract type BaseMessage since it does not have a default (parameterless) constructor."

私はMessageContract継承に見つけることができる限られた情報から、それだけで動作するはずと思われます。

私の質問は - これを機能させるためには何が欠けているのですか。または、おそらく、そのタイプのServiceContractに別々のOperationContractを定義する必要がありますか?欠点は、多くの追加のOperationContractsで終わる可能性があることです。

+0

PS - 私はnet.tcpとNetDataContractSerializerを使用しています(両方のクライアント/サーバー上)。 –

+0

ヘイフランク - "コードボタン"(010101010110のあるもの)を使用して、コードセクションをそのままフォーマットします。それらをうまくインデントし、シンタックスでそれらを強調表示します - 強くお勧めします! –

+0

ありがとうMarcは、あなたがそれをどうやって行ったのか疑問に思いました! –

答えて

0

これは、パラメータのないコンストラクタを持つ具体的なクラスになるようにBaseMessageを変更できますか?

エラーメッセージは、それが抽象的であるため、型BaseMessageのオブジェクトを初期化する方法がないことを伝えます。

+0

私はそれを試しましたが、メッセージはそのタイプにデシリアライズされ、TestMessageタイプ情報が失われました。 BeginFindRequestは現在、メッセージのタイプに基づいてロジックを適用します。つまり、タイプがBaseMessageであるためロジックが実行されません。 –

3

OK、最初の質問は:なぜあなたは本当にメッセージ契約を使用していますか?あなたは本当にそれが必要ですか?

通常、メッセージ契約は、SOAPメッセージのレイアウトを厳重に管理する必要がある場合にのみ使用されます。特定のヘッダーなどを必要とするコールする必要のあるレガシーシステムを満たすことができます。

「通常の」WCF呼び出しでは、メッセージ契約を使用する必要はほとんどありません。

[ServiceContract]を使用してサービスコール(サービス上のメソッド)を定義し、データ構造を[DataContract]として渡します。あなたがDataContractを持っているなら、あなたのサービスの継承/多型をどう扱うか(メッセージコントラクトコンストラクト以上)のオプションがあります。

マルク・

+0

私がMessageContractに行ったのは、WCFベストプラクティスの記事を読んでいるからです。私は今すぐ参照する記事を見つけようとしています。 DataContractに変換してすぐに問題が解決するかどうかを確認します。 ありがとうMarc –

+0

http://www.designpatternsfor.net/default.aspx?pid=99 - リスト5以降を参照してください(サービスメッセージパターン)。 –

+0

リンクありがとうございました。ロブがこの記事で作っていることは、私の好みのためには少し進んだようだ。ほとんどの場合、あなたは本当に彼が批判するこの「二重包装」には気をつけません。繰り返しますが、本当に正確なメッセージレイアウトを制御しなければならない場合、YES - メッセージ契約を使用します。しかし、私にとっては、それは何もしなくても、最後のリゾートのようなアプローチです。私はデフォルトの練習としてそれをお勧めしません。 –

0

はエラーは単にあなたがそれを使用することができ、デフォルトの空のコンストラクタを持って望んでいます。しかし、私はmarc_sに同意します。私が作業したプロジェクトでは、メッセージ契約をめったに使用していませんでしたが、私が覚えることができる唯一のケースは、ファイルチャンクがメッセージで受け渡されるファイル転送サービスの一部としてでした。

+0

私のコメントはcodemeitのとおり、抽象的なキーワードを削除するとデシリアライゼーションが有効になりますが、TestMessageオブジェクトが必要なときにBaseMessageオブジェクトが残っています。 DataContractに変換して問題が解決するかどうかを確認します。 –

+0

あなたはそれを抽象的に保つことができますが、BaseMessageに保護されたデフォルトのコンストラクタを与えますか? –

0

KnownType属性を使用して[ServiceContract]を飾るお試しください。 TestMessageは公共の操作から「可視」ではないので、配管工はそれを見てそれを扱う方法を知っています。

これは[DataContract]TestMessageとしてシリアライズできるようにする必要がある場合は、あなたの異なった「is a」や他のいくつかのキャスティングを介して複数のメッセージを処理する必要があることはまだ可能性が高いです。

+0

KnownType属性とServiceKnownType属性を試してみましたが、NetDataContractSerializerを使用しているので、これは必須ではありませんか? –

+0

面白いです...あなたがKnownType/ServiceKnownTypeを理解する必要はありませんが、KnownType/ServiceKnownTypeを使用しない場合、TestMessageのどこかに共通のdllを共有していることを意味します。そうでなければ、クライアントはTestMessageについて何も知りません。ただ、BaseMessageだけです。NetDataContractSerializerでの私の経験がnilなので、ここで仮説を立てています。私は、経験を得るためにそれを見つける必要があるかもしれません! :)どのようにデフォルトのDataContractSerializerを置き換えていますか?サービスがビジネスのために開かれる前にそれを置き換えていますか? –

+0

うまくいって、必要なライブラリはすべてサーバー/クライアント間で共有されています。 DataContractSerializerの置き換えに関しては、使用可能なさまざまな属性ベースのソリューションに対して、ファクトリメソッド型のアプローチを行ったので、どこにも属性を配置する必要はありませんでした。これは基本的に、すべてのDataContractSerializerOperationBehaviorsを自分自身のNetDataContractSerializerOperationBehaviourに置き換えたservicehost/proxyを返します。必要に応じてNetDataContractSerializerを提供します。 –

6

最後に、私は頭の上に釘を打つ、このブログの記事を見つけました -

Unfortunately the way that contracts are expressed in WCF makes is very easy to forget what their purpose is: to define the messages send to the operation and being sent back from the operation. In reality you have to think “how would I express this data in XML?”. XML doesn’t support inheritance so whatever you put in the contract is going to have to have some way of mapping to XML. The data contracts used to define the messages are simply a .NET typed convenience for generating the XML for the data you want to pass – if you view them any other way you are destined for a world of pain. So think about the data you want to pass, not how it may happen to be represented in your business layer and design your DataContracts accordingly.

http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx

だから私は、明示的な契約種別で追加の方法を提供することにリファクタリングされます。これにより、すべての型チェックを削除してサービス実装をクリーンアップすることもできます。

ありがとうございました。

+1

はい、はい - "OO"世界と "SOA"世界はまったく違う獣です..... XMLベースのメッセージングは​​、私たちがとても慣れ親しんだ継承や他のオブジェクト指向には適していませんに.... –