2016-07-30 17 views
1

背景WinFormsクライアントアプリケーションでコマンドパターンを使用するには?

私は二段C#.NETアプリケーションを構築しています:

  1. ティア1:MVP(モデル - ビュー - プレゼンター)デザインパターンを使用してのWinFormsクライアントアプリケーション。
  2. Tier 2:WebAPI Entity FrameworkとSQL Serverの上にあるRESTfulなサービス。

私が構築しているアプリケーションの詳細をお知りになりたい場合は、あまりにも完全な説明hereを付けました。

現在開発

現在、私はWinformsのクライアントに取り組んでいます。特に、私はこのクライアント内でコマンドパターンの適切な実装を網羅しようとしています。私は十分に幸運だったthis優れたブログの記事を横断して堅実なコマンドアーキテクチャを説明します。その投稿を補完するために、投稿者followed upがどのようにクエリからコマンドを分離するかを説明することで、これらのブログを読んだ後で、私の第2層(ウェブAPIサービス)がこれらの両方を実装することによって大きな利益を得ることは明らかです。一般的な実装では、優れた柔軟性、テスト容易性、および拡張性が実現します。私は物事(ティア1)のリサイズクライアント側でこれらのパターンを実装するに取り掛かる方法

私にはそれほど明確ではどのような質問は

です。クエリとコマンドは引き続きここで別々と見なされますか?ログイン試行などの基本的な操作を考えてみましょう。それはクエリかコマンドですか?最終的には、Webサービスからデータバック(サーバー上のユーザー情報)が必要なので、それがクエリだと思うようになります。新しいユーザーを作成するなどの別のケースはどうでしょうか。私はあなたがユーザー情報を格納し、サービスにそれを送信するコマンドオブジェクトを作成することを理解します。コマンドは火災であり、忘れているはずですが、コマンドが成功したことをサービスから確認する必要はありませんか?さらに、コマンドハンドラがvoidを返す場合、ユーザ作成要求が成功したかどうかをプレゼンタにどのように伝えますか?

任意の特定のUIタスク(ユーザー作成要求など)については、最終的にwinformsクライアントベースのクエリ/コマンドを持つことになります。また、Web APIサービスバージョンその要求を処理するコマンド/クエリ?

+0

リックの答えはスポット上にあります。私はそれに追加するものは何もありません。 – Steven

答えて

2

ここではクエリとコマンドは引き続き別個のものと見なされますか?

はい、通常はコマンドを実行し、この操作が実行された後にUIを更新する必要がある場合は、新しい情報を取得するためのクエリを実行します。例がこれを明確にするでしょう。

特定の領域に特定のガードを割り当てるとします。コマンド(DTOのみ)が必要とする唯一の情報は、ガードのIdとエリアのIdです。関連付けられたCommandHandlerは、これを処理するためのすべてのタスクを実行します。そのガードを他のエリアから削除し、利用不可能なものとして予約してください。

あなたのUIは変更を表示したいでしょう。UIにはおそらく、すべてのガードとその割り当てられた領域に関する何らかの種類のリストがあります。このリストには、List<GuardWithAreaInformationDto>を返す単一のGetActiveGuardsAndAreaQueryが入力されます。このDTOには、すべてのガードに関するすべての種類の情報を含めることができます。アトミックコマンド処理は、UI情報のわずかに異なる更新を必要とする類似しているが若干異なるUIから非常によく使用される可能性があるため、コマンドからこの情報を返すことは、懸念を明確に分離するものではありません。

ログイン試行など。それはクエリかコマンドですか?

IMOログイン試行ではありません。これは、クロスカッティングの問題であり、データが安全な接続の背後に隠れているという実装の詳細です。しかし、アプリケーションはこの詳細には関係してはいけません。 WebApiサービスをホストすることができる別の顧客とWindows Authenticationを使用できるActive Directoryドメインのアプリケーションを使用することを検討してください。その場合、ユーザーは自分のマシンにログインするだけで、セキュリティは通信中にクライアントとサーバーのOSによって処理されます。

AuthenticateToWebApiServiceCommandHandlerDecoratorを使用すると、これを参照しているパターンを使用すると、ユーザーにモーダルフォームで質問したり、設定ファイルから読み込んだりするなど、ログイン資格情報がサービスに役立つようにすることができます。 。

標準の種類のQueryを実行すると、資格情報が正常に実行されているかどうかを確認できます。アプリケーションには常にCheckIfUpdateIsAvailableQueryなどが必要です。照会が成功すると、ログイン試行は成功し、それ以外の場合は失敗しました。

コマンドハンドラからvoidが返された場合、ユーザ作成要求が成功したかどうかをプレゼンタにどのように伝えますか?

voidは何も返されませんが、これは実際には当てはまりません。なぜなら、何らかの例外(明確なメッセージが何が間違っているか)で失敗しなければ、成功したはずだからです。

上記のブログ記事の@dotnetjunkieには、コマンドから情報を返す方法が記載されていますが、投稿の上にコメントが追加されています。

要約すると、失敗したコマンドから明確な例外を投げる。これをうまく処理するために、抽象クライアント側の余分なレイヤーを追加することができます。一日の終わりに

public interface IPromptableCommandHandler<TCommand> 
{ 
    void Handle(TCommand command, Action succesAction); 
} 

public class PromptableCommandHandler<TCommand> : IPromptableCommandHandler<TCommand> 
{ 
    private readonly ICommandHandler<TCommand> commandHandler; 

    public PromptableCommandHandler(ICommandHandler<TCommand> commandHandler) 
    { 
     this.commandHandler = commandHandler; 
    } 

    public void Handle(TCommand command, Action succesAction) 
    { 
     try 
     { 
      this.commandHandler.Handle(command); 
      succesAction.Invoke(); 
     } 
     catch (Exception) 
     { 
      MessageBox.Show("An error occured, please try again."); 
      // possible other actions like logging 
     } 
    } 
} 
// use as: 
public void SetGuardActive(Guid guardId) 
{ 
    this.promptableCommandHandler.Handle(new SetGuardActiveCommand(guardId),() => 
       this.RefreshGuardsList()); 

} 

、任意のUIタスクのための(例えば:代わりに別のプレゼンターに直接commandhandlerを注入するあなたは、コンパイル時に1つだけ開いている一般的な実装を持っているIPromptableCommandHandlerを注入することができますユーザーの作成リクエスト)あなたはリサイズクライアントベースのクエリ/コマンドだけでなく、その端にリクエストを処理し、コマンド/クエリのウェブAPIサービスのバージョンを持ってしまうこと、それが終わるのでしょうか?

いいえ!

クライアント側あなたは、単にタスクがWEBAPIサービスにコマンドDTOを通過させることである単一のオープンジェネリックCommandHandlerProxyを作成する必要があります。 Writing Highly Maintainable WCF Services非常にうまくこれを処理するサーバー側のアーキテクチャについて説明します。別のフォローアップあなたが読むべきサービス側アーキテクチャの

。リンクされたプロジェクトには、WebApiの実装も含まれています。

+0

再びありがとう@リック、私はあなたの時間を感謝します!何が言われたのかを理解するために、私は再ハッシュをしましょう。コマンドの場合、winformsクライアントはコマンドオブジェクト(DTO)を作成します。このコマンドオブジェクトは、handleメソッドのパラメータとしてコマンドハンドラに渡されます。しかし、winformsクライアントのコマンドハンドラは、実際のコマンドが存在するWeb APIにコマンドを渡す汎用プロキシです(プロキシをPromptableComandHandlerに注入できる)。それは正しいと思いますか?クエリは同じ方法でプロキシを介して処理されますか? – Andrew

+1

@Andrewはい、正しく理解しました。クエリは同じパターンに従います。上記のプロキシはICommandHandlerを実装していますが、すべてのコマンドを同じ方法で処理するオープンな汎用実装です。 –

+0

確認のために@Ricに感謝します。それはかなり強力なものです。別の簡単な質問:コマンドやクエリ(DTO)は一般にフラット(プロパティのみ)であると考えられているのですか、それとも他のオブジェクトで構成できますか? – Andrew

関連する問題