我在我的Web API应用程序中使用AutoFac(使用此问题发布时可用的最新版本)。我的一个服务依赖项是AuditService
,它使用DbContext
类型的实例(我们现在称它为MyDbContext
)。我的大多数服务和MyDbContext
类型都使用InstancePerRequest注册。对于我的AuditService
我想要例外,我总是想要注入我MyDbContext
的拥有( new )实例。
问题:使用AutoFac注册,如何注册我的AuditService
,使其始终获得MyDbContext
的拥有(新)实例?
可以工作的内容:
MyDbContext
的构造函数中对AuditService
的创建进行硬编码,从而一起绕过AutoFac。MyDbContext
的新实例
MyDbContext
上定义第二个界面并提供第二次注册并使用InstancePerOwned
。我是否必须选择以上选项之一(如果是这样我会倾向于3 )或者我错过了一些简单的东西?有没有办法在我的注册码中定义我想要的东西?
// registration called in web api startup code
public void RegisterAutofac(ContainerBuilder builder)
{
builder.RegisterType<MyDbContext>()
.As<IMyDbContext>()
.InstancePerRequest();
builder.RegisterType<BusinessService>()
.As<IBusinessService>()
.InstancePerRequest();
builder.RegisterType<AuditService>()
.As<IAuditService>()
.InstancePerRequest();
}
public class AuditService
{
// expects an isolated instance on this request
private readonly IMyDbContext _dbContext;
public AuditService(IMyDbContext dbContext)
{
_dbContext = dbContext;
}
}
public class BusinessService
{
// expect a shared IMyDbContext instance across the request
private readonly IMyDbContext _dbContext;
public BusinessService(IMyDbContext dbContext)
{
_dbContext = dbContext;
}
}
这会导致异常
builder.RegisterType<MyDbContext>()
.As<IMyDbContext>()
.InstancePerRequest()
.InstancePerOwned<AuditService>();
Autofac.Core.DependencyResolutionException:“从请求实例的作用域中看不到带有'AuditService'标记的作用域。如果在执行Web应用程序期间看到这一点,通常表示注册为的组件SingleInstance()组件(或类似场景)正在请求每HTTP请求。在Web集成下,始终从依赖项解析器或请求生存期范围请求依赖项,而不是从容器本身请求。
at Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope) at Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable`1 parameter
我尝试撤消InstancePerOwned
和InstancePerRequest
调用的顺序,但这似乎没有效果,MyDbContext
实例同时重用BusinessService
和{{1}同一请求中的实例。我们使用AuditService
中的object.ReferenceEquals
对此进行了测试,并在两个实例的ApiController
字段中传递。
_dbContext
答案 0 :(得分:1)
尝试从InstancePerRequest
切换到InstancePerLifetimeScope
。在大多数应用中,无论如何这通常都表现相同and is the way to share registrations across apps that both do and don't have per-request semantics。 (也就是说,这很常见。)
在您的上下文对象上有InstancePerLifetimeScope
后,您可以use Owned<T>
in your AuditService
constructor获取新的副本。
因此...
builder.RegisterType<MyDbContext>()
.As<IMyDbContext>()
.InstancePerLifetimeScope();
...然后
public AuditService(Owned<IMyDbContext> dbContext)
请注意,AuditService
将负责在dbContext
完成后处理Owned<T>
,因此您必须手动处理({1}} Filter = "(|(objectCategory=person)(objectCategory=computer)(objectCategory=group))"
)。但如果你已经有一些一次性的事情发生,那不应该是一个大问题。