49

私はインターネットから読んだことがありますが、これにはインターフェイスが使用されているというポイントがあります

  • TDD メソッドを使用する
  • 永続化エンジンを置き換える

しかし、この時点でインターフェースがどのように役立つかを理解できませんReplace persistance engine。基本的な(ジェネリックなしの)リポジトリを作成していると考えてみましょうEmployeeRepository

public class EmployeeRepository
{
  public employee[] GetAll()
  {
     //here I'll return from dbContext or ObjectContex class
  }
}

では、インターフェースはどのように理解されるのでしょうか?

そして、私がインターフェースを作成したとしたら、なぜアップキャストが使用されるのですか? 例えば

 IEmployee emp = new EmployeeRepository() ;
 vs
 EmployeeRepository emp = new EmployeeRepository();

リポジトリ パターンに関するインターフェイスのその他の有用性についても、正確に説明してください。

4

2 に答える 2

91

では、インターフェースはどのように登場するのでしょうか?

このような:

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 で行う方法の例を次に示します。

  1. Ninject.MVC3 NuGetをインストールする
  2. 生成され~/App_Start/NinjectWebCommon.csたコードでは、1 行のコードで EF 実装を使用することを決定するだけです。

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IEmployeeRepository>().To<EmployeeRepositoryEF>();
    }        
    

このようにして、これらのリポジトリ クラスを手動でインスタンス化する必要がなくなり、アップキャストなどについて心配する必要がなくなります。それらを管理し、定義された実装をコントローラーコンストラクターに注入するのは、依存性注入フレームワークです。

この構成を変更するだけで、コントローラーのコードを 1 行も変更することなく、データ アクセス テクノロジを切り替えることができます。このようにして、分離した単体テストも有効になります。コントローラ コードはレポジトリに弱く結合されているため (導入したインターフェイスのおかげで)、単体テストで行う必要があるのは、その動作を定義できるレポジトリにモック実装を提供することだけです。これにより、データベースなどに依存することなく、インデックス コントローラー アクションの単体テストを行うことができます。完全な隔離。

また、ASP.NET MVC の TDD と DIに関する次の記事もご覧ください。

于 2012-05-16T09:57:49.203 に答える
15

リポジトリをインターフェースとして公開します。

public interface IEmployeeRepository
{
    List<Employee> GetAll();
}

これにより、デフォルトの実装など、インターフェイスのさまざまな実装を行うことができます。

public class EmployeeRepository : IEmployeeRepository
{
    public List<Employee> GetAll()
    {
        // Return from db.
    }
}

またはテスト1:

public class TestEmployeeRepository : IEmployeeRepository
{
    public List<Employee> GetAll()
    {
        // Stub some dummy data.
    }
}

リポジトリを消費するコードは、インターフェースの使用にのみ関心があります。

IEmployeeRepository myRepo = MyRepositoryFactory.Get<IEmployeeRepository>();

シークレットソースは、ファクトリ、またはインターフェイスを使用可能なタイプに解決するための別のメカニズムです(NinjectやCastle Windsorなどの依存性注入フレームワークがこの役割を果たします)。

重要なのは、消費するコードは実装を気にせず、コントラクト(インターフェース)だけを気にするということです。これにより、テスト目的で実装を非常に簡単に交換でき、緩い結合が促進されます。

明確にするために、インターフェースの使用とリポジトリパターンの間に具体的なリンクはありません。それは、それらを利用できる別のパターンにすぎません。

于 2012-05-16T09:57:36.283 に答える