4

我的具体上下文是一个自托管的 Nancy 应用程序,我在其中使用 RavenDb 嵌入式文档数据库。

我的引导程序如下所示:

public class MyBootstrapper : DefaultNancyBootstrapper
{
    protected override void ConfigureApplicationContainer(TinyIoCContainer container)
    {
        base.ConfigureApplicationContainer(container);

        container.Register<IDocumentStore>(CreateDefaultStore());
        container.Register<IDoSomething, MyOtherType>().AsSingleton(); // implements IDisposable
    }

    private static IDocumentStore CreateDefaultStore(){...}
}

问题是我期望在 NanyHost 停止时调用 IDocumentStore 和我的自定义一次性类型的 Dispose 方法。

NancyHost 实现 IDisposable,TinyIoCContainer 实现 IDisposable,如果我将实现 IDisposable 的类型注册到请求容器中,它将被释放。我几乎可以肯定,当主机被处置时,容器将被处置,并且所有已注册的实例都将被处置。

我知道我可以在引导程序之外存储对文档存储的引用,并在主机停止后将其处理掉,我还可以想到一些其他技巧,例如让引导程序实现 IDisposable 并在主机停止后手动处理它,但我在跳跃有一种更自动的方式来处理所有已注册实例的处置。

我是否错过了一些在应用程序容器中注册的单例实例上调用 Dispose() 的巧妙方法?

我的猜测是,由于主机和应用程序容器预计会一直存在到应用程序结束,因此处理容器不是优先事项,但如果是这种情况,这似乎是一种不好的做法。

更新:发布后,我在 nancy 组上找到了这个线程,其中有一些与此相关的信息,但有点旧。

4

2 回答 2

2

虽然这不应该是应用程序关闭所必需的,但在自托管和 OWIN 场景中,您可能希望“重新启动”服务器组件,而不拆除 AppDomain - 在这些场景中,对最终确定更具确定性显然是有益的。

为此,我将引导程序更改为一次性,使我们的引导程序基类释放应用程序容器(如果它实现 IDisposable),并连接主机以在释放主机时将其全部释放:

https://github.com/NancyFx/Nancy/pull/1268

于 2013-10-17T08:41:27.240 回答
2

阅读您提供的源代码,RavenDb 没有完全实现 IDIsposable 模式。根据最佳实践,实现 IDisposable 的类应该有终结器,它清理非托管资源。在这种情况下,GC 会做任何需要的事情。

在您提供的 RavenDb 代码中,Dispose 方法不处理任何非托管资源,因此如果未调用它,则不应有任何泄漏。这当然假设托管资源EmbeddableDocumentStore,如果他们拥有非托管资源(我没有检查),则引用了“正确的” IDisposable 模式实现。

如果您仍有疑虑,您可以:

  1. 向 RavenDb 提交错误请求,以便他们修复
  2. 在 DocumentStore 周围使用一个包装器,它正确地实现了 IDisposable 模式。

无论如何,除非存在已证明的错误/需要,否则我不认为“在 .Net 框架上中继来完成它的工作”是一件坏事。假设应用程序容器存在于应用程序的整个生命周期中,当应用程序终止时,GC 将负责适当的处理。

于 2013-10-16T13:00:30.830 回答