Ninject:是否可以在SingletonScope中使用父对象,在TransientScope中使用子对象?

几个星期以来,我一直在用这种方式绞尽脑汁……我现在拥有的是这样的:

  • 一堆*Service
  • 所有这些都依赖于通过EF访问数据库的不同*Repository
  • 为了允许unit testing,将DbContext注入到存储库中。 (所以我不能用于处理上下文)

要正确处理注入的EF上下文,我可以在InRequestScope()或简单的自定义作用域中运行我的依赖树 – InScope(c => new object())和所有其他级别的InParentScope()

这两种方法都会在每个请求期间创建和处理大量对象。 另外我们讨论的是单页应用程序,因此95%的查询(大约50个)将在2个请求中执行,因此InRequestScope()似乎不是一个好主意。 此外, *Service类不保持状态,因此可以是InSingletonScope()并且可以最小化对象创建量。

问题

是否有可能在InSingletonScope()拥有parent *Service*Repository类,并以某种方式将EF DbContext注入到每次访问时将返回一个新实例的范围,并使用NInject来表示IDisposable

我知道在创建对象时会注入依赖项,但这仍然可以通过某种方式进行管理吗?

不,这是不可能的。 如果你考虑一下,你应该明白为什么。

单个对象将在应用程序的生命周期中存在。 InRequestScope对象在请求的生命周期中存在。 由于您的单例存储库将永久存在,并且它将保存对DbContext的引用(因为它是依赖项),这意味着如果没有您的存储库具有某种释放机制,则无法对dbcontext进行垃圾收集。

即使您确实提供了这样的机制,您也必须有另一种机制来在下一个请求中重新获取新实例,因为不会创建新的单例存储库(因此它的构造函数将不会被调用,因此它的依赖关系将无法解析,因此它无法了解新的dbcontext)。

因此,实际上,使InRequestScope对象成为单个对象的依赖关系将有效地使InRequestScope对象成为单例,否则该对象将从单例下面处理掉,这可能是坏事。

另外,我不同意你的事实是你的存储库有状态。 状态是DbContext本身。 由于Singleton是一个应用程序范围的静态实例,因此您可以为使用您的应用程序的所有用户提供相同的实例,这意味着它也会提供相同的DbContext,这是一个巨大的禁忌,因为您的用户会踩到彼此DbContext状态。

同样,您的服务也是有状态的,因为它们具有存储库,正如我刚才指出的那样,DbContexts是有状态的。

你想要做的只是简单地使你的服务,存储库和DbContexts都是InRequestScope。

我不明白为什么这种方法会“在每个请求期间创建大量对象”。 重点是它只为每个请求创建每个对象类型的一个实例。