web-dev-qa-db-ja.com

WPFクライアントとWCF二重サービスを使用したMVVMのベストプラクティス

WCFデュプレックスサービスからデータを受信するWPFアプリケーションの設計方法について考えていましたが、過剰なエンジニアリングを恐れています。

サービスとコールバックインターフェイスを内部的に実装する「プロキシクライアント」ライブラリを作成することにより、WPFクライアントからWCF通信を完全に抽象化することを考えました。

この方法では、WPFアプリケーションでコールバッククラスを作成する必要はありませんが、そのサービスのコールバックメソッドが呼び出されたときに呼び出されるプロキシクライアントのイベントにサブスクライブします。これにより、サービス参照をWPFから隠すこともできます。

次に、WPFで行うことは次のとおりです。

var client = new ApiClient(); //This is the client library
var stuff = client.GetStuff(); //Some service method
client.StuffDeleted += OnStuffDeleted; //Event that is invoked by library on callback

おそらく、すべてのViewModelが呼び出すシングルトンオブジェクトとして、クライアントを1回だけインスタンス化します。

次に、WCFサービス参照生成クラス(データコントラクト)とほぼ同じ「モデル」クラスを作成し、プロキシクライアントの上に別のレイヤーを追加し、オートマッパーを使用してモデルを作成し、次に返すことで、これをさらに進めることができると考えましたそれらをデータコントラクトクラスの代わりにWPFに渡します。

WCFサービスから完全に分離する方法を考え、さらにレイヤーを追加することで、モデルにメタデータを追加してから返すことができます。WPF側では、これらのモデルを使用して、ViewModelを構築します。表示/バインドのみ。

WCFクライアントは単一の独立したコンポーネントであるため、このようなクライアントを使用すると、ビジネスロジックとエラー処理を一元化しやすくなり、ユニットテストを簡単に実行できるようになります。

問題は、これを過度に設計することを恐れていることです。データベースにはEFエンティティがあり、WCFサービスには独自のDTOクラスがあり、モデルにはViewModelがあります。また、WCFから生成されたクラスがINotifyPropertyChangedインターフェイスを実装していることにも気づきました。これは、それらがモデルとして(またはサービスに更新を送信するために)使用されることを意図していたと思います。

主な質問を箇条書きにまとめてみます。

  • M-V-VMでは、サービス参照生成クラスをモデルとして使用することは良い習慣ですか?
  • プロキシクライアントを使用してWPFからWCFを完全に抽象化することには大きなメリットがありますか?
    • コールバックメソッドは、WPFがサブスクライブされているイベントを呼び出します
  • 生成されたサービス参照クラスがINotifyPropertyChangedを実装するのはなぜですか?

このデザインはやりすぎですか?

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

UPDATE:

私がやろうとしていることの視覚化:

enter image description here

ご覧のとおり、中央のプロキシクライアントには2つの層(クラス)があります。

最初のクラスは、WPFがシングルトンとしてインスタンス化し、モデルクラスを取得するために使用するクラスです。

2番目のクラスは、サービス参照クライアントのラッパーであり、最初のレイヤーによって呼び出されます。これは純粋にデータアクセスを目的としています。

WPFがサブスクライブするイベントになるコールバックメソッドを追加していません。

5
Shahin Dohan

過去にこのような状況があり、アプリケーション用に別のWPFモデルレイヤーを作成することになりました。

それ以来、どれだけの変化があったのかはわかりませんが、その理由は次のとおりです。

  • アプリケーションに読み取り専用プロパティが必要であり、DataContractsによって生成されたDTOは読み取り/書き込み可能である必要がありました

  • 一部のクラスは非常に大きかったが、UIモデルはデータの非常に小さなセクションしか必要としませんでした。

  • UIレイヤーの一部のプロパティにはカスタムロジックがありました。たとえば、dbプロパティを123のintとして保持する必要がありましたが、UIの目的のために「000123」の文字列が必要でした

  • WCFまたはEFレイヤーを他の代替レイヤーに置き換えるなど、レイヤーのテクノロジースタックを変更する可能性を将来的に開いておく必要がありました。それらを分離することで、アプリケーション内のすべてのものではなく、1つのレイヤーを書き換えるだけで済みます。

  • 暗号化レイヤーをいくつかのデータに追加して、データが保存時または転送時に暗号化されるようにしたかったのです。

私たちの最終結果は:

  • アプリケーションが使用するUIモデルのみを作成し、UIが必要とする正しいプロパティ、データ型、およびスコープを使用するProject for WPFモデル。

  • データアクセスレイヤーのプロジェクト。データベースレイヤーに転送するためにWPFモデルをDTOまたはEFモデルに変換します。これにもAutoMapperを実際に使用しました。

  • WCFから自動生成されたクラスを含む実際のWCFプロジェクト

  • 自動生成されたEFモデルと手順を含む実際のEFプロジェクト

私が正しく覚えていれば、WPFアプリケーションレイヤーから、次のようになります。

ISomeService service = DAL.SomeService();
ISomeModel stuff = service.GetStuff();

DALは、一部のインターフェイスに対応するサービスクラスを返します。サービスレイヤーを他のものに置き換えたい場合は、WPFアプリケーションの他の部分に影響を与えることなくできます。

さらに、ISomeModelは、カスタムロジックやイベントなど、WPFアプリケーション自体に固有のアイテムを実装できます。データベースに送信/受信するデータオブジェクトに関連付ける必要はありませんでした。

1
Rachel