これがベスト プラクティスとは言えませんが、これが私が使用しているものとその理由です。
1. リポジトリ。
それらは次のように構成されています。
IRead<>
、およびの 3 つの基本的なインターフェイスがありIReadCreate<>
ますIReadCreateDelete<>
。
interface IRead<T>
{
T FindOne(int id);
IQueryable<T> GetOne(int id);
IQueryable<T> FindAll(Expression<Func<T, bool>> predicate);
}
interface IReadCreate<T> : IRead<T>
{
T Create();
void Create(T entity);
}
interface IReadCreateDelete<T> : IReadCreate<T>
{
void Delete(int id);
void Delete(T entity);
void DeleteWhere(Expression<Func<T, bool>> predicate);
}
他のすべてのインターフェイスは次のようになります。
interface ICategoriesRepository : IReadCreate<Category>
{
IQueryable<Category> GetAllActive();
}
そしてそれらはすべて、依存するデータ ソースに追加の便利な機能を提供します。つまり、実装リポジトリ内の他の型付きリポジトリにアクセスできません。これはServicesで行う必要があります。(下を見てください。)
このアプローチの主な目的は、呼び出し元のコード (すべてのリポジトリ、サービス、およびその他のコントラクトが別の DLL プロジェクトで (インターフェイスとして) 定義されているため、別のアセンブリから) 何ができるか (アイテムの読み取りや作成など) を示すことです。できません(アイテムの削除など)。
2. サービス
ビジネスロジックを実装するためのサービスと最良の方法。それらはすべての重要なロジック メソッドを実装する必要があります。そのような実装を実現するには、いくつかのリポジトリ依存が必要になりますDependency Injector
。次のような依存関係プロパティを挿入できるため、Ninjectを使用することを好みます。
internal class CategoriesService : ICategoryService
{
public ICategoriesRepository CategoriesRepository { get; set; }
public IWorkstationsRepository WorkstationsRepository { get; set; }
// No constructor injection. I am too lazy for that, so the above properties
// are auto-injected with my custom ninject injection heuristic.
public void ActivateCategory(int categoryId)
{
CategoriesRepository.FindOne(categoryId).IsActive = true;
}
}
サービスの目標は、コントローラーとリポジトリーからビジネス ロジックを排除することです。
3.ViewModel
あなたが言ったようにクールなことですが、その理由は、なぜあなたがそれらを自分自身で構築しているのか、私には理解できないことです. そのためにオートマッパーを使用しています(クエリ可能な拡張機能付き)。これにより、次のようなビューを作成できます。
モデルが必要なビューがあるとしましょう。IEnumerable<TicketViewModel>
私がすることは:
public class FooController : Controller
{
public IMappingEngine Mapping { get; set; } // Thing from automapper.
public ITicketsRepository TicketsRepository { get; set; }
public ViewResult Tickes()
{
return View(TicketsRepository.GetAllForToday().Project(Mapping)
.To<TicketViewModel>().ToArray();
}
}
それでおしまい。基礎となるデータソースを呼び出すリポジトリへの単純な呼び出し (別のパターン。その抽象化はテストにのみ必要なので、それについては書きません)。データベース (または実装するものIDataSource<T>
) への呼び出しを行います。Automapperは、単一のリクエストでクロステーブルを含む、ViewModel 列に必要なだけを取得するフォーム データベースに自動的にマップTicket
します。TicketViewModel
結論
言いたいことはまだまだたくさんありますが、これがあなたの思考の糧になることを願っています。私が使用するすべてのパターンとプログラムは次のとおりです。
- オートマッパー (マッピング);
- Ninject (依存性注入);
- リポジトリ (データ アクセス);
- データ ソース (データはデータ ソースから読み取られます);
- サービス (データの双方向性);
- ViewModel (データ転送オブジェクト);
- 多分私が編集して追加する何か他のもの.