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