使用Autofac进行MVC 3通用存储库注入

时间:2012-04-26 15:54:10

标签: asp.net-mvc-3 generics dependency-injection repository-pattern autofac

继承人的问题: 我正在研究使用通用存储库的解决方案,存储库工作正常等等。 mather是我试图重构代码以便在Controllers构造函数上启用注入依赖项。为什么我想实现这个?,该解决方案使用TDD,我们希望简化测试应用程序的方式。我不想创建假货,因为我们正在做实际的,而不是我真的想利用EF存储库的好处,并在编译时解决,如果我使用FakeRepository(在级别实体进行更改)和真正的存储库,使更改数据库。

我使用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...

}

这些行代表Fake Repository

    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:

中尝试了这个
    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根本不知道如何解析控制器构造函数。

提前致谢!

2 个答案:

答案 0 :(得分:4)

您正在向IRepository<IEntity>注入DemoController,这很奇怪,因为IEntity不是具体实体而DemoController可能需要具体实体(例如Customer)。由于您要将IRepository<T>映射到具体的Repository<T>,因此您需要进行以下注册:

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

您可能还需要根据Web请求或在生命周期范围内注册DbContext。将MyController注册为PerHttpRequest

似乎很奇怪

答案 1 :(得分: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