2

这是问题所在:我正在研究使用通用存储库的解决方案,存储库工作正常等等。问题是我试图重构代码以启用对控制器构造函数的注入依赖项。为什么我要实现这个?,解决方案使用 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 根本不知道如何解析控制器构造函数。

提前致谢!。

4

2 回答 2

4

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

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

您可能还需要DbContext根据 Web 请求或在生命周期范围内注册。MyController注册as似乎很奇怪PerHttpRequest

于 2012-04-27T07:36:27.143 回答
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

于 2012-04-27T14:52:58.897 回答