2

Heres the問題: 一般的なリポジトリを使用するソリューションでは、リポジトリは正常に動作します。 matherは、コントローラのコンストラクタに対して依存性を注入できるように、コードをリファクタリングしようとしています。なぜ私はこれを達成したいのですか?ソリューションはTDDを使用していますので、アプリケーションのテスト方法を簡単にしたいです。実際にEFリポジトリの利点を活用し、FakeRepository(レベルエンティティでの変更)と実際のリポジトリを使用している場合はコンパイル時に解決したいのではなく、実際にやっているように偽物を作成したくないデータベースへの変更。MVC 3汎用リポジトリAutofacでの注入

私は永続化技術としてEFを使用しています。

これらの行はリポジトリ

public class Repository<T> : IRepository<T> where T 
           : class, IEntity 
{ 
    private readonly DbSet<T> dbset; 
    private readonly DbContext _context; 

    public Repository(DbContext context) 
    { 
     _context = context; 
     dbset = context.Set<T>(); 
    } 

    public void Add(T entity) 
    { 
     //Some logic... 
    } 

    public void Update(T entity) 
    { 
     //Some logic... 
    } 

    //more methods... 

} 

にこれらの行を表し、これらの線は、リポジトリのインターフェース契約を表す

public class FakeRepository<T> : IRepository<T> where T 
           : class, IEntity 
{ 
    private readonly DbSet<T> dbset; 
    private readonly DbContext _context; 

    public FakeRepository(DbContext context) 
    { 
     _context = context; 
     dbset = context.Set<T>(); 
    } 

    public void Add(T entity) 
    { 
     //Some logic... 
    } 

    public void Update(T entity) 
    { 
     //Some logic... 
    } 

    public void Remove(T entity) 
    { 
     //Some logic... 
    } 

    //more methods... 
} 

偽リポジトリを表します。

public interface IRepository<T> 
        where T : class, IEntity 
{ 
    void Add(T entity); 
    void Remove(T entity) 
    void Remove(T entity); 
    //more methods... 
} 

これは、そのコンストラクタがpreviosタイプのGenericを期待するコントローラの例です。

public class DemoController : Controller 
{ 
    private readonly IRepository<IEntity> _repository; 
    public DemoController(IRepository<IEntity> repository) 
    { 
     _repository = repository; 
    } 

    public ViewResult Index() 
    { 
     return View(_repository.FindAll()); 
    } 

} 

したがって、問題は...どのようにタイプをAutofacコンテナに登録するのですか?私はこれを達成する方法について多くのフォーラムを見ていますが、この必要性を解決するアプローチを見つけられませんでした。

のglobal.asaxでこれをItried:

protected void Application_Start() 
    { 
     ConfigureIoC(); 
     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 
    } 

    private static void ConfigureIoC() 
    { 
     var builder = new ContainerBuilder(); 
     builder.RegisterControllers(typeof(Global).Assembly); 

     //At this section the dependencies are added in order to resolve Types. 
     builder.RegisterType<MyController>().InstancePerHttpRequest(); 

     builder.RegisterType<MyContext>().As<DbContext>(); 
     builder.RegisterType<Repository<Entity>>().As<IRepository<IEntity>>(); 

     var container = builder.Build(); 
     DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
    } 

私はまた、個々のタイプを登録しようとしたが、autofacは、単純に、コントローラのコンストラクタを解決する方法を知りません。

ありがとうございます。

+0

Iはまた、次aproachを試みたが、エラーを取得: builder.Register <リポジトリ>(X =>新しいリポジトリ(新しいDbContext()))のような>()。 ;私はこのコードを実行する場合、私が得る gerrorをフォローです: 型「CHR.Data.Common.Repository.Metadata.MetadataRepository'1は[CHR.Model.Metadata.ExaminationElement]」 にサービスを提供するために割り当て可能ではありませんすべての訴訟? – Charles

答えて

1

あなたのアドバイスをいただきありがとうございます。ドキュメントや他のブログを見て、私が共有している解決策を見つけました。 また、私はあなたの選択肢を他のものより速いかどうかを調べるよう試みます。

protected void Application_Start() 
    { 
     ConfigureIoC(); 
     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 
    } 

    private static void ConfigureIoC() 
    { 
     var builder = new ContainerBuilder(); 
     builder.RegisterControllers(typeof(Global).Assembly); 

     //First we register the types for DemoController. 
     builder.RegisterType<Repository<Entity>>().As<IRepository<IEntity>>(); 
     //Then we register the controller itself resolving/indicating the target type to use on the constructor. 
     builder.Register(c => new DemoController(c.Resolve<IRepository<IEntity>>())); 

     //We build the container. 
     var container = builder.Build(); 
     DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
    } 

はautofacの別の方法を使用して、別のアプローチをTheresのが、従来の方法は自動的に十分な依存性を解決するため:。

ジェネリック基づいコンストラクタ注入を解決するためのコードは以下の通りである焦点私はちょうどまた、私はあなたがサンプルプロジェクトをダウンロードして、Autofacは、このマザーでどのように機能するか非常に明確示しできるリンクを共有するだけで参照

  builder.RegisterType(typeof(DemoController)).UsingConstructor(typeof(IRepository<IEntity>)); 

するための方法をあげますよ。

Autofac T

+0

最終的な解決策は、上記のコードとリポジトリとコントローラコンストラクタの "InstancePerHttpRequest"です。これは、コントローラとリポジトリ(コントローラがリポジトリを注入するためコントローラ)のインスタンスの一貫性を保証するためです。 – Charles

4

あなたはIEntityが、具体的な実体ではなく、DemoControllerはおそらく(例えばCustomerなど)具体的な実体を必要とするので、非常に奇妙である、DemoControllerIRepository<IEntity>を注入しています。あなたが具体的なRepository<T>IRepository<T>をマップしたいので、次の登録が必要となります:

builder.RegisterGeneric(typeof(Repository<>)) 
    .As(typeof(IRepository<>)); 

はまた、おそらくWebリクエストごととしてDbContextを登録、または寿命の範囲にする必要があります。そしてMyControllerPerHttpRequestと登録するのは奇妙なことです。

+0

THanks steven、私はInstancePerHttpRequest節を自分のコードで見逃していたdbコンテキストに追加しました。この時点であなたの解決策を試しています。 – Charles

関連する問題