为什么 NamedScopes 从终结器调用 dispose 方法?

Why NamedScopes invoke dispose methods from finalizer?

我注意到当我在 Ninject 命名范围内使用 IDisposable 对象时,我的 Dispose 方法是从终结器调用的。但我的对象或其中的一些引用可能在那时已经完成。

我错过了什么吗?这是正确的行为还是错误?

堆栈跟踪:

в NInjectNamedScopes.User.ChatService.Dispose()
в Ninject.Activation.Strategies.DisposableStrategy.<Deactivate>b__0(IDisposable x)
в Ninject.Activation.InstanceReference.IfInstanceIs[T](Action`1 action)
в Ninject.Activation.Pipeline.<>c__DisplayClass6.<Deactivate>b__4(IActivationStrategy s)
в Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)
в Ninject.Activation.Caching.Cache.Forget(CacheEntry entry)
в Ninject.Activation.Caching.Cache.Forget(IEnumerable`1 cacheEntries)
в Ninject.Activation.Caching.Cache.Clear(Object scope)
в Ninject.Extensions.NamedScope.DisposeNotifyingObject.Dispose(Boolean disposing)
в Ninject.Infrastructure.Disposal.DisposableObject.Finalize()

因为 ninject 仍然引用了您的 IDisposable,所以您的 IDisposable 应该不可能已经完成。但是,在您的情况下, Dispose 方法是从终结器调用的,这似乎很奇怪。你能提供堆栈跟踪吗?

命名范围行为

默认情况下 InNamedScope,ninject 保留 WeekReferenceDefinesNamedScope (root) 并定期检查它是否仍然存在。一旦它被检测为垃圾收集,该范围的 InNamedScope-对象将被释放(Ninject 保持对这些的强烈引用)。

要确保 InNamedScope-d 对象在范围根对象之后立即处理,请将 INotifyWhenDisposed 添加到范围根。

  1. 一般来说,从终结器访问其他托管对象是一种非常糟糕的做法。
  2. 我在 NamedScopes 个扩展的源代码中发现了一些其他与性能相关的问题。

所以是的,这是一个错误,我建议大家根本不要使用 NamedScopes 扩展,直到它被修复。我个人进行了一些性能测试并选择了另一个 IoC 容器 AutoFac,它的工作速度提高了一个数量级。