では、インターフェースはどのように登場するのでしょうか?
このような:
public interface IEmployeeRepository
{
Employee[] GetAll();
}
そして、好きなだけ実装することができます:
public class EmployeeRepositoryEF: IEmployeeRepository
{
public Employee[] GetAll()
{
//here you will return employees after querying your EF DbContext
}
}
public class EmployeeRepositoryXML: IEmployeeRepository
{
public Employee[] GetAll()
{
//here you will return employees after querying an XML file
}
}
public class EmployeeRepositoryWCF: IEmployeeRepository
{
public Employee[] GetAll()
{
//here you will return employees after querying some remote WCF service
}
}
and so on ... you could have as many implementation as you like
ご覧のとおり、リポジトリをどのように実装するかはそれほど重要ではありません。重要なことは、すべてのリポジトリと実装が定義されたコントラクト (インターフェース) を尊重し、すべてGetAll
が従業員のリストを返すメソッドを所有していることです。
そして、このインターフェースを使用するコントローラーができます。
public class EmployeesController: Controller
{
private readonly IEmployeeRepository _repository;
public EmployeesController(IEmployeeRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var employees = _repository.GetAll();
return View(employees);
}
}
コントローラーがリポジトリの特定の実装に依存しなくなったことがわかりますか? 知っておく必要があるのは、この実装がコントラクトを尊重することだけです。あとは、好みの依存性注入フレームワークを構成して、希望する実装を使用するだけです。
これを Ninject で行う方法の例を次に示します。
- Ninject.MVC3 NuGetをインストールする
生成され~/App_Start/NinjectWebCommon.cs
たコードでは、1 行のコードで EF 実装を使用することを決定するだけです。
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IEmployeeRepository>().To<EmployeeRepositoryEF>();
}
このようにして、これらのリポジトリ クラスを手動でインスタンス化する必要がなくなり、アップキャストなどについて心配する必要がなくなります。それらを管理し、定義された実装をコントローラーコンストラクターに注入するのは、依存性注入フレームワークです。
この構成を変更するだけで、コントローラーのコードを 1 行も変更することなく、データ アクセス テクノロジを切り替えることができます。このようにして、分離した単体テストも有効になります。コントローラ コードはレポジトリに弱く結合されているため (導入したインターフェイスのおかげで)、単体テストで行う必要があるのは、その動作を定義できるレポジトリにモック実装を提供することだけです。これにより、データベースなどに依存することなく、インデックス コントローラー アクションの単体テストを行うことができます。完全な隔離。
また、ASP.NET MVC の TDD と DIに関する次の記事もご覧ください。