如何限定自我?

How to scope to self?

我们有一个使用工作单元模式的 Web 服务。工作单元模式需要在多个地方使用相同的 DbContext。所以我们的第一个想法是将 dbContext 的范围限定为请求范围,如下所示:

kernel.Bind<IStore>().ToConstructor<TestContext>(_ => new TestContext(Env.DbServerInstance, databaseName)).InRequestScope();
kernel.Bind<IUnitOfWork>().To<DbContextUnitOfWork>();

它工作得很好,直到我们需要在同一请求范围内使用两个工作单元对象。哎呀!我们收到一条错误消息,指出 DbContext 已被释放。

InRequestScope 几乎起作用了,因此我们认为我们需要将范围规则从 dbContext 中移走,并在 IUnitOfWork 对象中应用某种类型的范围规则。这是我们目前的尝试:

kernel.Bind<IStore>().ToConstructor<TestContext>(_ => new TestContext(Env.DbServerInstance, databaseName));
kernel.Bind<IUnitOfWork>().To<DbContextUnitOfWork>().InScope(ctx =>
        {
            return ctx.???;
        });

但是我们如何从 ctx 上下文对象访问实例化的 DbContextUnitOfWork 呢?我们可以访问 DbContextUnitOfWork 类型(来自 ctx.Request.Service),但这似乎对我们没有帮助。换句话说,我想要这样的东西:

kernel.Bind<IUnitOfWork>().To<DbContextUnitOfWork>().InSelfScope();

或者有没有更好的方法来实现我们想要的结果?

更新

@Luke McGregor - 是的,IUnitOfWork 使用了 IStore 接口。我还阅读了您建议的 Captive Dependency - 谢谢。但是,在我们的例子中,IUnitOfWork 是我们对象图的根节点,我们只需要 IStore 每个实例 的单个实例 IUnitOfWork.

例如:假设 UnitOfWork(称之为服务 A)依赖于服务 B 和 C,这两个服务需要一个 IStore(服务 D),那么服务 B 和 C 必须 共享服务 D 的同一个实例。(就好像服务 D 从服务 A 的角度来看是一个单例。)因此,如果我创建两个 UnitOfWork 实例(A1 和 A2),那么系统应该只包含两个服务实例D(即 D1 和 D2)。

此外,当 A1 被销毁时,它的整个对象图也会被销毁,A2 也是如此。

这是我们正在努力实现的目标的图表。

因此,A1 的对象图完全独立于 A2 的对象图,服务 D 在每个相应的对象图中充当单例。

那么,我们如何配置 IUnitOfWork and/or IStore 来使其工作? 谢谢。

您始终需要在 lower or equal scope than its dependencies*.

范围内确定消费者的范围

例如,如果您的上下文绑定在请求范围内,您的 IUnitOfWork 事物(我假设它使用 IStore)应该绑定在请求范围或瞬态范围内。

IUnitOfWork 的任何消费者也需要在请求范围或更低范围内绑定(我想这就是您所缺少的部分,某处可能是线程或单例范围)。

*瞬态范围是该规则的一个例外,因为它的范围由消费者决定。 EG 它将在其注入的事物范围的末尾处理。

经过更多的挖掘,我们找到了我们要找的东西。

Ninject.Extensions.NamedScope 扩展提供了几个新的范围规则,其中之一称为 InNamedScope,它似乎可以完美地满足我们的需求。