2

繼承人問題: 我正在使用使用通用存儲庫的解決方案,存儲庫工作正常,等等。主要是,即時通訊嘗試重構代碼,以便在控制器構造函數上啓用注入依賴。爲什麼我想要實現這個目標?解決方案使用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類型的泛型。

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

我也嘗試下一個的形式給出,但得到一個錯誤: builder.Register <庫>(X =>新的存儲庫(新的DbContext()))作爲>() ; 的的GError如果我運行此代碼,我得到的是後續: 類型「CHR.Data.Common.Repository.Metadata.MetadataRepository'1 [CHR.Model.Metadata.ExaminationElement]」不是分配給服務 任何消化? – Charles 2012-04-26 17:45:28

回答

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的另一種方法的另一種方法,但由於以前的方法自動解析依賴性其足夠。我只是把方法僅供參考

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

而且我分享一個鏈接,你可以下載一個示例項目,顯示非常清晰Autofac如何在這個馬瑟。

Autofac T

+0

最終的解決方案是上面的代碼以及用於存儲庫和控制器構造函數的「InstancePerHttpRequest」,這是爲了保證控制器和存儲庫(控制器因爲它注入存儲庫)的實例的唯一性。 – Charles 2012-05-09 05:32:52

4

你注入IRepository<IEntity>DemoController,這是很奇怪的,因爲IEntity不是一個具體的實體,DemoController可能需要一個具體的實體(如Customer)。既然要映射IRepository<T>混凝土Repository<T>,你需要以下注冊:

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

你也可能需要註冊DbContext按Web請求,或在一生範圍。將MyController註冊爲PerHttpRequest似乎很奇怪。

+0

THanks史蒂文,我添加了InstancePerHttpRequest子句到我的代碼上錯過的數據庫上下文。我正在嘗試你的解決方案。 – Charles 2012-04-27 14:59:59