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

时间:2013-08-13 07:46:21

标签: c# architecture ninject

我一直在用这种方式乱搞我的大脑几个星期......我当前拥有的是:

  • 一堆*Service
  • 所有这些都取决于通过EF
  • 访问数据库的不同*Repository
  • 要允许单元测试,将DbContext的派生注入到存储库中。 (所以我不能使用using处理上下文)

要正确处理注入的EF上下文,我可以在InRequestScope()或简单的自定义范围中运行我的依赖关系树 - 顶级InScope(c => new object())InParentScope()其他级别。

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

问题

是否可以在*Service中拥有父*RepositoryInSingletonScope()类,并以某种方式将EF DbContext注入到每次访问时都会返回新实例的范围内并将使用NInject尊重IDisposable

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

1 个答案:

答案 0 :(得分:4)

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

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

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

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

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

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

您要做的只是将您的服务,存储库和DbContexts全部放入InRequestScope。

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