私が現在構築しているシステムでは、コマンド パターンを使用して可能なすべての操作を実行します。私は CommandMessage と CommandHandler のアプローチを選択し、ロジックをデータから分離しました。これは今のところ問題なく動作しますが、検証という問題に遭遇しました。
コマンドが実行できるかどうかを実際に検証するにはどうすればよいですか?
現在、私はCanExecute(ICommandExecutionContext context)
on every コマンドを持っており、実行できるかどうかを判断する責任があります。ICommandExecutionContext
次に、各コマンドでAが型チェックされ、正しいコンテキスト型であるかどうかが確認され、その後、その情報によってコマンドがそのコンテキストで実行可能になるかどうかが確認されます。
ICommandService
名前、コンテキスト、およびメッセージに基づいて、コマンドを検証および実行できるにすべてがラップされます。それ以外にも、コマンド実行に関するイベントを発行し、権限チェックを実行します。
この問題は、UI (ASP.NET MVC 3 アプリケーション) に起因します。各ビューに有効なコマンドのみを表示したいのですが、本当に気に入った解決策を見つけることができませんでした。現在、私のコントローラーは、次のような具体的なコンテキストが与えられた場合に、コマンドを実行できるかどうかをコマンド サービスに尋ねます。
var executionContext = new SystemCommandExecutionContext("SignInCommand", CurrentPrincial);
var canExecute = _commandService.CanExecute(executionContext);
/* Handle the result to enable or disable the action link */
具体的なドメイン オブジェクトで機能する他の種類のコマンドについては、同じコマンド サービス メソッドを使用しますが、次のようにドメイン オブジェクト ID を渡す別のコンテキストを使用します。
[HttpPost, Authorize, ValidateAntiForgeryToken /* etc. */]
public ActionResult Delete(Guid id)
{
/* Note the additional object id in the context */
var executionContext = new EntityCommandExecutionContext("DeletePersonCommand", CurrentPrincipal, id);
var canExecute = _commandService.CanExecute(executionContext);
if(canExecute)
{
var message = new DeletePersonCommandMessage(id);
var isValid = _commandService.IsValid(executionContext, message);
if(isValid)
{
var result = _commandService.Execute(executionContext, message);
/* More logic here... Not very DRY :( */
}
}
}
あまりDRYではありませんが、上記は今のところ大丈夫だと思います。しかし、私が達成したいのは、CanExecute の結果に基づいて、アクション リンクを無効にすることです。
どうやってやるの?
各ビューのすべてのコマンド リンクを「ハードコード」することにしたので、コマンド名などのコレクションを渡す必要はありません。そのパスは難しすぎます (誰かが賢いアイデアを持っている場合を除きます ;)
私の現在のスタックは、NHibernate、Castle Windsor、ASP.NET MVC 3、AutoMapper で構成されています。