我正在尝试使用Autofac注册通用组件。我遇到的问题类似于下面链接中的问题(错误消息是相同的)。 Binding autofac with webapi using generic repository
我正在使用洋葱架构(http://jeffreypalermo.com/blog/the-onion-architecture-part-1/)。 DbContexts位于单独的层中,而业务层是获取数据并执行与业务规则相关的各种事务的层。上层只会知道IBaseDbManager接口。我有一个垂直层,负责解决依赖关系。
在我的代码示例和Autofac配置下面:
商业类:
public class BaseDbManager<TContext> : IBaseDbManager where TContext : DbContext, IBaseContext
{
private readonly TContext _context;
public BaseDbManager(TContext context)
{
_context = context;
}
public Partner GetPersonInfo(Expression<Func<Person,bool>> predicate)
{
var person = _context.Persons.Where(predicate).FirstOrDefault();
return person;
}
}
业务界面:
public interface IBaseDbManager
{
Partner GetPersonInfo(Expression<Func<Person, bool>> predicate);
}
DB CONTEXT:
[Database]
public class BaseContext : DbContext, IBaseContext
{
public BaseContext()
: base((string) ConnectionHelper.BaseConnectionString())
{
Database.SetInitializer<BaseContext>(null);
}
public virtual DbSet<Person> Persons { get; set; }
}
上下文接口:
public interface IBaseContext
{
DbSet<Partner> Partners { get; set; }
}
AUTOFAC MODULE:
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<BaseContext>().As<IBaseContext>().InstancePerLifetimeScope();
builder.RegisterType(typeof(BaseDbManager<>)).As<IBaseDbManager>().InstancePerLifetimeScope();
}
问题是Autofac不知道如何在没有无参数构造函数的情况下解析IBaseDbManager。我需要通过Autofac解决TContext。如何配置Autofac来解决这些问题?我尝试注册为通用的,并基于构造函数,它也不起作用。如果我向约束添加new()并在无参数构造函数中创建一个实例,那么它可以工作......我不想这样解决它。
我错过了什么?
答案 0 :(得分:2)
问题是Autofac不知道如何在没有无参数构造函数的情况下解析IBaseDbManager。
这不是问题。构造函数不是问题,Autofac不会对构造函数构成任何约束。
这里的问题是,给定open-generic BaseDbManager<T>
,Autofac不知道要创建它的封闭通用版本,因为给定的IBaseDbManager
抽象是非泛型的。它无法为您推断出通用类型。
有几种解决方案,但由于应用程序中不同上下文类型的数量很可能非常有限(通常只有1),因此在注册中指定此上下文类型最有意义。例如:
builder.RegisterType(typeof(BaseDbManager<BaseContext>)).As<IBaseDbManager>()
.InstancePerLifetimeScope();
如果BaseContext
是你唯一的上下文类型,那么使BaseDbManager<T>
非泛型更有意义,因为如果你实际上计划改变类型参数T
那么它只是有意义的{1}}。
我有两个与TContext约束匹配的对象(BaseContext和FakeBaseContext)。 BaseContext查询数据库,FakeBaseContext使用专门为单元测试创建的伪数据。
这似乎不是另一个上下文类的正当理由;上下文是一组实体的定义;在测试期间,您拥有相同的实体集。
答案 1 :(得分:0)
在查看Autofac文档的几个部分之后,我发现注册文件与Steven的方法相结合,允许Autofact正确解析依赖关系(参见下面的链接):
http://docs.autofac.org/en/latest/register/parameters.html?highlight=WithParameter
模块注册我的最终编码如下:
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<BaseContext>()
.As<IBaseContext>()
.InstancePerLifetimeScope();
builder.RegisterType<BaseDbManager<BaseContext>>().As<IBaseDbManager>()
.WithParameter(new TypedParameter(typeof(BaseContext), new BaseContext()))
.InstancePerLifetimeScope();
}
额外反馈将不胜感激。我会继续重构我的代码,因为我认为它可以改进。