2017-08-09 26 views
0

我很努力地实现一个功能来为Ninject IoC启用自定义会话范围。我的要求是,对于唯一的会话id(int),我会得到绑定到特定接口的对象的新实例。 第二个要求是它必须可以在Get被调用的地方。如何将会话ID传递给Ninject容器以获取会话绑定的对象实例?

问题是,IKernel.Get <>无法传递会话ID。我不能使用.InScope(),因为静态实例将无法访问当前会话ID。 (可以使用无Session.Current模式)。

会话只能通过唯一的整数进行区分,并且可以同时运行多个会话。

除了每次创建一个单独的容器之外,还有什么想法?恐怕它可能是昂贵的。复制容器? Ninject有可能吗?

谢谢,Radek

+1

防止让对象图的构造依赖于运行时数据。阅读[this](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=99)以获取更多信息。 – Steven

回答

1

你的假设是错误的。

  • InScope不需要静态字段。方法签名是InScope(Func<IContext, object> scope)。所以你有权访问IContext - 这不是静态的。
  • Get重载接受IParameter s。这些放在IContext。您可以为会话范围创建自定义IParameter实现。所以有一种方法可以将您的会话传递给Get

但是,只有一个整数作为会话ID可能无法正常工作。由于范围对象需要是引用类型,而不是值类型,因此需要涉及拳击。 Ninject可能无法正确支持这一点 - 以防比较引用而不是整数值。此外,清理(IDisposable.Dispose()调用)可能会提前完成。 Ninject保持对范围的弱引用。如果范围对象不执行INotifyWhenDisposed它定期检查弱引用是否已经死亡。当它死了,它会做资源清理。当然,如果ninject获得自己的“盒子”对象并且只保留一个弱引用,GC可以随时收集这个对象。意味着你的资源可以在范围实际结束之前处理。

所以你需要将你的scope-id包装在一个对象中(并且保留对这个对象的引用,而不仅仅是该值),并且最好使它实现INotifyWhenDisposed以进行确定性资源清理。


提示:也许InCallScope - 包含在Ninject.Extensions.NamedScope将是你的使用情况更适合。

另一种可能的选择是每个会话采用ChildKernel。这与每个会话创建一个内核类似 - 但它不是重量级的。

+0

“静态字段”只是一个首字母缩写词/快捷键。但我对定制IParameter实现更感兴趣,这听起来很有趣。所以,总之我可以提供额外的参数,一个盒装会话ID。你能否概述一下我将如何解决基于此的新实例或现有实例?你的意思是: InScope(x => x.Parameters.FirstOrDefault(p => p.Name ==“SessionId”))? 其实你不需要实现一个新的IParameter,只需在调用Get时提供它。像Get (新参数(“SessionId”,_currentBoxedSessionId));对? –

+0

@RadekStrugalski你不需要一个自定义参数,但恕我直言,它只是一个更清洁。由你决定。 “boxed session id” - 不,我会创建一个具有int字段的Session类。然后,您需要在应用程序中使用此类/对象来引用会话,而不仅仅是参数。如果你只是在参数中使用它,那么没有人会保留对它的引用,并且最终会得到......以及“未定义”的行为。 – BatteryBackupUnit

+0

@RadekStrugalski,除非您提供[MCVE](https://stackoverflow.com/help/mcve),否则很难提供示例性实现来展示解决问题的方法。 – BatteryBackupUnit