自动处置Autofac中的子生命周期作用域



很多时候,我在autofacc中创建子生命周期范围只是为了替换或补充父生命周期范围中的注册。从那时起,我只使用子生命周期作用域。autofacc文档声明子作用域不会被自动处理:

子作用域未被自动处理

虽然生存期作用域本身实现了IDisposable,但是您创建的生存期作用域不会自动为您处置。如果您创建了一个生命周期作用域,您有责任调用Dispose()来清除它并触发组件的自动处置。

但是,在这种情况下,我确实希望自动处理子节点。

到目前为止,我想到的解决方法是让子作用域处理父作用域。像这样:
ILifetimeScope scope = ...;
var childScope = scope.BeginLifetimeScope();
childScope.Disposer.AddInstanceForDisposal(scope);
scope = childScope;

因为我从来没有跟踪过scope,只有childScope,我需要一种方法来处理父节点。

使问题进一步复杂化的是,每个父节点可以有多个子节点作用域。所以我不能在这些情况下这么做。我只希望在处置最后一个子进程时处置父进程。要做到这一点,我认为在父进程中,我必须在每次调用BeginLifetimeScope()时注册一些专门用于引用计数的服务,并在处置子进程时减少引用计数。

我不确定我的方法是否正确,所以我想看看这里是否有更好的解决方案。我正在将我的代码库从UnityContainer迁移到autofacc。之前的代码有一个UnityDisposer对象,它将从上到下遍历父/子树并处理所有内容,但我在Autofac中没有得到这种层次结构。

<标题>

编辑对于我推测的解决方案有一些疑问,所以我写了一个示例应用程序来看看会发生什么:

class ThingA : IDisposable
{
public ThingA()
{
Console.WriteLine("Construct ThingA");
}
public void Dispose()
{
Console.WriteLine("Dispose ThingA");
}
}
class ThingB : IDisposable
{
public ThingB()
{
Console.WriteLine("Construct ThingB");
}
public void Dispose()
{
Console.WriteLine("Dispose ThingB");
}
}
public static class Program
{
public static void Main()
{
ContainerBuilder builder;
builder = new ContainerBuilder();
builder.RegisterType<ThingA>().InstancePerLifetimeScope();
ILifetimeScope container1 = builder.Build();
container1.Resolve<ThingA>();
var container2 = container1.BeginLifetimeScope(builder2 =>
{
builder2.RegisterType<ThingB>().InstancePerLifetimeScope();
});
container2.Disposer.AddInstanceForDisposal(container1);
container1 = container2;
container1.Resolve<ThingB>();
container1.Dispose();
}
}
我得到的输出是:
Construct ThingA
Construct ThingB
Dispose ThingB
Dispose ThingA

所以据我所知,对于一个线性的父母/孩子关系,这似乎是有效的。但这并不能解决多子女问题。为了说清楚,我对线性情况的解也不是特别满意。

从autofacc的角度来看,您实际上必须开始跟踪父作用域和子作用域,以便您可以选择何时处置它们。这有点像蜘蛛侠的情节:能力越大责任越大。

有时,这就像用using语句包装一组不同的工作单元一样简单。在异步情况下,比如ASP。. NET,中间件和HttpContext等地方开始发挥作用。

把父母从孩子的监护下赶出去是个坏主意。除此之外,一旦父母被处置,你就不能真正从孩子那里解决问题(是的,我理解父母会以某种方式坚持到最后一个孩子结束,但事实仍然存在);我们确实看到过一些奇怪的边缘情况,人们有意或无意地将父节点从子节点下处理掉,这取决于它是如何被连接起来的,以及事情发生的顺序,你最终可能很难排除涉及ObjectDisposedException的异常。

如果你想想你在autofacc上下文的之外尝试做什么,试图让系统处理自己是一种糟糕的设计模式,就像让子作用域以某种方式负责父作用域一样。例如,如果你有一些其他的父/子关系,你想这样做,更多时候你会看到一些外部的协调器来处理引用计数和处理——在逻辑父/子关系之外。

我建议这样做——实际上跟踪父级和子级作用域与协调器类的一些性质并让编排器监视所有子作用域的消失。

另外,它将使其他情况更容易,如"我创建了父节点,我创建了一个子节点,当我试图创建第二个子节点时,它被处理并清理了父节点。"线程的东西。您将能够在您的编排器代码中考虑到这一点。

相关内容

  • 没有找到相关文章

最新更新