1

クライアントが Windows フォーム アプリであり、サーバーが Windows サービスでホストされる WCF サービスであるクライアント/サーバー アプリケーションを作成しています。アプリケーションの両側を制御していることに注意してください。

インターフェイスに対するコーディングの実践を実装しようとしています。つまり、クライアント アプリケーションによって参照される共有アセンブリがあります。このプロジェクトには、クライアントに公開される WCF ServiceContracts とインターフェイスが含まれています。インターフェイスのみをクライアントに公開しようとしているため、特定の実装ではなく、コントラクトのみに依存します。これを行う理由の 1 つは、クライアントを再コンパイルおよび再デプロイすることなく、いつでもサービスを実装してドメインを変更できるようにするためです。この場合、インターフェース/コントラクトは変更されません。WCF サービスを再コンパイルして再デプロイするだけです。

私が今直面している設計上の問題は次のとおりです。たとえば、クライアントが具体的な実装ICustomerについて知らない場合、クライアントでオブジェクトの新しいインスタンスを作成するにはどうすればよいですか? CustomerDB に保存する新しい顧客を作成する必要があります。

依存性注入または Factory クラスを使用して新しいオブジェクトをインスタンス化する必要がありますか? それとも、クライアントが具体的な実装の新しいインスタンスを作成できるようにする必要がありますか?

私は TDD を行っていません。通常は、ICustomerまたはその他の公開されたインターフェイスを 1 つだけ実装します。

4

4 に答える 4

1

私のWCF開発で同じ質問に出くわしました。実際には、通信の両側でデータ コントラクトの具体的な実装が必要です。では、それらの実装はどこから来たのでしょうか? サーバー側では、実装は通常、すべてのビジネス ロジックなどを含むビジネス オブジェクトです。そして、これらの実装をクライアントで使用したくない場合は、それらを共有アセンブリに配置することを意味し、いくつかの理由でそれを使用したくありません。したがって、クライアントには独自の個別の具象クラスのセットが必要です。それらを自分で作成するか、自動的に生成するかのいずれかです。

自分で実装を書くのは面倒です。通常、クライアント オブジェクトは単純であり、実際に行うことはデータを格納することだけなので、おそらくコード生成が適しています。その時点で、いくつかの選択肢があります。サービス参照の追加を介して WSDL に基づいてコードを生成するか、何らかのフレームワークを使用してインターフェイスに基づいて実行時にクラスを生成することができます。

どちらの方法でも、インターフェイスに対するコーディングの利点が得られます。インターフェイスが変更されない限り、サーバーとクライアントを個別に変更および再構築できます。インターフェースが WSDL である場合と CLR インターフェースである場合がありますが、WCF は CLR インターフェースに基づいて WSDL を生成するため、これらはまったく同じものです。個人的には、[サービス参照の追加] が気に入っています。これは既に存在し、プロジェクトに依存関係を追加しないためですが、好きな方を選んでください。

于 2010-01-14T15:13:34.940 に答える
1

.NET クライアントの生産性向上として、アプリケーションの両側を制御するエンタープライズ アプリでこれを内部的に行うことについて説明しました。陪審員はまだこれについて出ていません。

ただし、共有ライブラリ (クライアントとサービスの間) でコントラクトを持つことについて議論する場合、通常、これにはサービスコントラクト ([ServiceContract]) とサービス操作のパラメーターのエンティティ([DataContract]) の両方が含まれます。 これらの型は、伝統的に、これらのサービス操作に期待される具体的な型です。

あなたの場合、DTO は ICustomer などのインターフェイスを実装し、Customer を表すプロパティを実装し、[DataContract] です。型が (NetDataContractSerializer を使用して) サービスに正しくシリアル化されると仮定すると、クライアントは必要な具体的な実装をほとんど突き詰めることができると思います。サービスは、ICustomer に準拠するものにのみ関心があります。

クライアントは、必要な ICustomer の具体的なインスタンス (OrderingCustomer、FinanceCustomer など) を作成できます。 タイプがサービス ICustomer インターフェイスを実装している限り、正しくシリアル化されていれば、サービス操作に値として渡すことができます。例えば

public class OrderingCustomer : ICustomer
{
}

あなたが目指しているクライアントへの影響をゼロにできるかどうかはわかりません。インターフェイス タイプを変更する (ICustomer にプロパティを追加する) 場合、クライアントは再コンパイルする必要があります。パラメータを追加すると、コア .NET タイプ (int など) の 1 つであっても、クライアントは再コンパイルする必要があります。これは、クライアントがサービス参照を更新して再コンパイルするのと実質的に同じ影響です。

ただし、サービスの実装または動作を変更しない場合(バグ修正など)、どちらの場合 (共有型またはサービス参照) でも、クライアントとの間の契約が変更されない限り、クライアントは何もする必要はありません。もちろん、これが間違っていることを証明する、これに関するあなたの経験も聞きたいです!

この慣行は、.NET 以外のシステムとの相互運用性のストーリーを完全に台無しにしてしまいます。私がこれを敷物の下に一掃するのと同じように、どこかの部門があなたの超気の利いたサービスについて聞いて、それを使いたいと思うでしょう....そして、彼らはJavaスタック、COBOL、またはFORTRANなどを実行するでしょう.. :)

于 2009-08-17T12:31:31.630 に答える
0

おそらく答えはもう出ていると思いますが、私は現時点で似たようなことをしようとしています - リポジトリを WCF サービスに挿入して、これらのサービスがデータベースにアクセスするコードに依存しないようにします。あなたの質問に答えるのに役立つと思われる次の記事を見つけました。

http://geekswithblogs.net/ballhaus/archive/2009/12/12/unit-testing-your-wcf-service.aspx http://www.silverlightshow.net/items/Deep-dive-into-WCF-part -1-TDD.aspx

HTH

シアラン

于 2010-03-30T23:11:42.870 に答える
0

さて、あなたは2つのことを混乱させている(または混同している)と思います:

  • サービス コントラクトは、サービスが公開する機能のみを記述しますFindCustomerAddCustomerたとえば、これらの操作では、クライアントはインターフェイスを知るだけで済みます。クライアント プロキシを追加すると (「サービス参照の追加」を使用して)、次のことも行われます。YourServiceClientこれらの呼び出しを実装するクライアント プロキシで具象クラスを取得する

  • データ コントラクトは、行き来するデータを記述します。それらは XML スキーマに基づいているため、常に具象クラス(など) ですCustomerInvoiceこれらはサーバーで定義され、クライアントは、サービス参照を追加するときに、サービスによって発行された WSDL/XSD からそれらの型を推測し、クライアント側でこのデータの具象クラスを作成します。これらはサーバーが使用するものとまったく同じクラスではありません- それらは同じように見え、主な要件は XML へのシリアル化と XML からの逆シリアル化が同じであることですが、実際には異なるクラスです (.NET 名前空間が異なる可能性が最も高い)。

したがって、機能のために、実際にはインターフェイスとして共有するだけでよいサービス コントラクトがあります。これで十分であり、クライアントは YourServiceClientそのインターフェイスから「プロキシ クラス」(クラス) を作成します。クライアントは、サーバーの実装やその具象クラスに依存しません。

一方、交換されるデータ (デフォルトで XML 形式にシリアライズされる) は、常に WSDL/XSD から推論される具象クラス (インターフェースなし) になります。クライアントはサーバーのクラスに依存せず、サーバーのクラスのみに依存します。いわば「XMLシリアライゼーションフィンガープリント」です。

今、これがあなたに大いに役立つかどうかはわかりません:-)しかし、少なくとも、物事が少し明確になるので、うまくいけばうまくいきますか?

マルク

于 2009-08-14T13:51:18.367 に答える