继承人的问题: 我正在研究使用通用存储库的解决方案,存储库工作正常等等。 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根本不知道如何解析控制器构造函数。
提前致谢!
答案 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如何在这个方面发挥作用。