抽象ビュー:あるレイヤーから別のレイヤーに情報を渡したい(注:このスレッドに適したタイトルがある場合はお知らせください)。
ビューおよびサービスレイヤーと通信するViewModelがあります。そして、永続層とのサービス層通信があります。
次のクラスがあるとしましょう。
public class EmployeeViewModel()
{
// The following properties are binded to my View (bidirectional communication)
public Firstname ...
public Lastname ...
public Email ...
public void PerformingSearch()
{
...
EmployeeService.Search(...);
...
}
}
public class EmployeeService()
{
public List<Employee> Search(...)
{
// Searching in db
}
}
ViewModelからサービスレイヤーにデータを渡すためのベストプラクティスは何ですか(検索の実行など)?
いくつかのオプションが表示されます(ViewModelパースペクティブ):
この問題のデザインパターンはありますか?それはどのように呼ばれますか?どのオプションが最適ですか?私は何かを逃しましたか?
あなたの特定の例は、あなたの現在のアーキテクチャには、データアクセス層へのプロキシとして機能するサービス層が含まれていることを示しています。アーキテクチャに関するより深い知識がなければ、環境が許す限りシンプルに保つための可能な解決策を提案します。
それでは、可能なソリューションモデルを取得するための戦略を選択してみましょう。ユーザーストーリーは、「ユーザーが情報を送信して従業員のリストを取得する」のように聞こえます。
簡略化された現在のユースケース:
リファクタリングされたユースケースの例:
簡単に見えますか?
要するにCQS:
すべてのメソッドは、アクションを実行するコマンドか、呼び出し元にデータを返すクエリのいずれかである必要がありますが、両方ではないことを示します。
あなたの特定のケースでは、クエリに焦点を当てる必要があります。
クエリ:結果を返し、システムの監視可能な状態を変更しないでください(副作用はありません)。
しかし、これはどのように役立ちますか?どれどれ。CQSクエリ側の非常に優れた詳細な説明は、Stevenの「一方...私のアーキテクチャのクエリ側」ブログ投稿で完全に読むことができます。
クエリオブジェクトのインターフェイスを定義する
public interface IQuery<TResult> {}
クエリハンドラの定義:
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
これが「検索」クエリオブジェクトの実装です。これは事実上、「情報を渡す方法」の質問に対する答えです。
public class FindEmployeeBySearchTextQuery : IQuery<Employee>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
そして最後に、クエリオブジェクトに渡すクエリハンドラを作成します。
public class FindEmployeeBySearchTextQueryHandler
: IQueryHandler<FindEmployeeBySearchTextQuery, List<Employee>>
{
private readonly IDbContext db;
public FindEmployeeBySearchTextQueryHandler(IDbContext db)
{
this.db = db;
}
public List<Employee> Handle(FindEmployeeBySearchTextQuery query)
{
return (
from employee in this.db.employees
where employee.FirstName.Contains(query.FirstName) ||
employee.LastName.Contains(query.LastName) ||
employee.Email == query.Email
select employee )
.ToList();
}
}
注:このHandle()
実装例ではEntity Frameworksを使用しIDbContext
ているため、必要に応じてこれを修正/変更する必要があります(ADO.NET、NHibernateなど)。
そして最後にあなたのビューモデルで:
public class EmployeeViewModel()
{
private readonly IQueryHandler _queryHandler;
public EmployeeViewModel(IQueryHandler queryHandler)
{
_queryHandler = queryHandler;
}
public void PerformingSearch()
{
var query = new FindEmployeeBySearchTextQuery
{
FirstName = "John",
LastName = "Doe",
Email = "[email protected]"
};
List<Employee> employees = _queryHandler.Handle(query);
// .. Do further processing of the obtained data
}
}
この例では、依存性注入を使用していることを前提としています。
IQueryHandler実装をビューモデルコンストラクターに挿入し、後で受け取った実装で作業します。
このアプローチを使用すると、コードがよりクリーンになり、ユースケース主導型になり、責任の分離が向上します。これにより、横断的関心事を簡単にテストして装飾できます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加