我有非一次性类ReadModelRepository
,它依赖于(但不拥有)一次性类ReadModelDbContext
的实例。在Module
内,我想配置我的Autofac 3.0.2容器,以便仅在创建ReadModelDbContext
个对象时解析ReadModelRepository
(每个依赖项一个实例)。
这就是我目前所拥有的:
builder.RegisterType<ReadModelRepository>().As<IReadModelRepository>();
builder.Register(c => new ReadModelDbContext(_connectionStringName)).AsSelf();
但是,我不希望任何任意类能够使用模块提供的注册来解析ReadModelDbContext
。实际上,其他类可能需要解析不同的ReadModelDbContext
个实例。
要解决此问题,我可以使用WithParameter
,就像在此片段中一样:
builder
.RegisterType<ReadModelRepository> ().As<IReadModelRepository> ()
.WithParameter (
(p, c) => p.ParameterType == typeof (ReadModelDbContext),
(p, c) => new ReadModelDbContext (_connectionStringName));
但是,当生命周期范围解析ReadModelDbContext
(或实际解析组件的生命周期)结束时,我还需要Autofac自动处理ReadModelRepository
。使用WithParameter
,这似乎不起作用。
所以,实质上,我只想在外部组件的上下文中注册一个依赖项,当最外层组件的生命周期范围结束时调用Dispose
。这可能吗?
答案 0 :(得分:1)
也许,这会对你有帮助。
public class RepositoryManager : IDisposable
{
private ILifetimeScope m_RootLifetimeScope;
private ILifetimeScope m_RepositoryScope;
private bool m_Disposed;
public RepositoryManager(ILifetimeScope rootLifetimeScope)
{
m_RootLifetimeScope = rootLifetimeScope;
}
public IReadModelRepository CreateReadModelRepository()
{
m_RepositoryScope = m_RootLifetimeScope.BeginLifetimeScope(
builder =>
{
builder.RegisterType<ReadModelRepository>().As<IReadModelRepository>();
builder.Register(c => new ReadModelDbContext(_connectionStringName)).AsSelf();
});
return m_RepositoryScope.Resolve<IReadModelRepository>();
}
public void Dispose()
{
if (m_Disposed) return;
m_RepositoryScope.Dispose(); //ReadModelDbContext will be disposed
m_Disposed = true;
}
}
//registration
builder.RegisterType<RepositoryManager>().InstancePerDependency();
//using
using (var repositoryManager = yourContainer.Resolve<RepositoryManager>())
{
IReadModelRepository repository = repositoryManager.CreateReadModelRepository();
}
答案 1 :(得分:0)
我建议让ReadModelRepository
依赖Func<Owned<ReadModelDBContext>>
。
类似的东西:
using Autofac.Features.OwnedInstances;
class ReadModelRepository : IReadModelRepository
{
public ReadModelRepository(Func<Owned<ReadModelDBContext>> contextFactory)
{
_ctxFactory = contextFactory;
}
public DoSomethingUseful()
{
using (var context = _ctxFactory())
{
// use context.Value in here;
// it will be disposed when exiting the block
...
}
}
private readonly Func<Owned<ReadModelDBContext>> _ctxFactory;
}
然后你可以随意注册ReadModelRepository和ReadModelDBContext。
这种方法无法解决阻止其他类解析ReadModelDBContext
的问题,但是您可以通过将所有这些类型内部添加到程序集来玩可见性游戏,除了IReadModelRepository
。如果你无法进入该类型,你当然不能从容器中要求一个实例。
答案 2 :(得分:0)
过了一段时间,我实际上采用了不同的方法:我用私钥注册内部组件(ReadModelDbContext
):
var privateKey = new object();
builder.Register(c => new ReadModelDbContext(_connectionStringName)).Keyed<ReadModelDbContext>(privateKey);
builder.Register(ctx => new ReadModelRepository(ctx.ResolveKeyed<ReadModelDbContext>(privateKey))).As<IReadModelRepository>();
由于没有其他人拥有密钥,这有效地使ReadModelDbContext
注册成为ReadModelRepository
的私密。