9

统一 2.0:

默认情况下,RegisterInstance 使用 ContainerControlledLifetimeManager。当 Unity 容器被释放时,它会在实例上调用 Dispose(如果是 IDisposable)。

就我而言,这不是我想要的。该实例由另一个类拥有和处置;Unity 应该只注入引用。所以我用:

container.RegisterInstance(instance, new ExternallyControlledLifetimeManager());

Unity 文档(在Understanding Lifetime Managers 下)指出:

使用 RegisterInstance 方法注册现有对象会产生与刚刚使用 RegisterType 注册生命周期容器相同的行为。因此,在使用非默认生命周期管理器时,建议不要使用 RegisterInstance 方法注册现有对象,调用 RegisterInstance 的线程除外。

这是什么意思?

同一部分还指出:

如果您使用 RegisterInstance 方法注册了对象的现有实例,则容器会为对 Resolve 或 ResolveAll 的所有调用或当依赖机制将实例注入其他类时返回相同的实例,前提是满足以下条件之一:

  • 您已指定容器控制的生命周期管理器
  • 您已使用默认生命周期管理器
  • 您在使用不同的生命周期管理器时在注册实例的同一上下文中解析。

在将 RegisterInstance 与 ExternallyControlledLifetimeManager 一起使用后,我尝试在不同的线程中解决,并且它起作用了 - 我得到了单例实例。

我的代码与创建实例注册部分中的示例匹配。不过,我想确保我理解上下文警告。

需要明确的是,我总是希望 Unity 容器注入我注册的实例,而不考虑线程等,并且我希望 Unity 处理它。我这样做正确吗?

4

2 回答 2

5

请注意ExternallyControlledLifetimeManager。您仍然必须在容器外的某处保存对实例的引用。一旦丢失引用,您可能会丢失实例,因为ExternallyControlledLifetimeManager仅保留WeakReference. 如果您没有正常的参考垃圾收集器可以收集您的实例。在我的博客上查看示例。

于 2011-03-16T23:11:59.007 回答
2

我觉得你很好。只有当您使用不使用的 PerThreadLifetimeManager 时,所有每个线程的注释才重要。这只是 MSDN 文章部分的笨拙措辞。

这不是标准术语,但在本文中,它们的含义是由特定的生命周期经理定义的。对于 PerThreadLifetimeManager,您的上下文就是您的线程。对于 HierarchicalLifetimeManager,您的上下文是容器层次结构中的特定容器。

对于 ExternallyControlledLifetimeManager 没有特定的上下文,因此您可以完全忽略相关注释。

作为旁注,请确保在您仍然希望容器解决它们时不处置您的实例。如果这样做,您的解析请求将返回与您预期不同的实例,或者抛出异常,具体取决于容器是否可以构造您的类型。

于 2011-03-16T23:05:23.487 回答