我正在努力实现为Ninject IoC启用自定义会话范围的功能。我的要求是,对于唯一的会话id(int),我将获得绑定到特定接口的新对象实例。 第二个要求是必须可以在调用Get的地方使用。
问题是IKernel.Get<>无法传递会话ID。我也不能使用.InScope(),因为静态实例将无法访问当前会话ID。 (无会话。可以使用当前模式)。
会话只能通过唯一的整数来区分,并且可以同时运行多个会话。
除了为每个会话创建一个单独的容器外,还有什么想法?恐怕它可能很贵。复制容器?是否可以使用Ninject?
谢谢,拉德克
答案 0 :(得分:1)
你的假设是错误的。
InScope
不需要静态字段。方法签名为InScope(Func<IContext, object> scope)
。因此,您可以访问IContext
- 这不是静态的。Get
重载接受IParameter
。这些都放在IContext
上。您可以为会话范围创建自定义IParameter
实现。因此,有一种方法可以将您的会话传递给Get
。但是,只有一个整数作为会话ID可能不起作用。由于范围对象需要是引用类型,而不是值类型,因此涉及到拳击。 Ninject可能无法正确支持 - 如果它比较引用而不是整数值。此外,清理(IDisposable.Dispose()
调用)可能会提前完成。 Ninject对范围保持弱引用。如果范围对象未实现INotifyWhenDisposed
,则它会定期检查弱引用是否已死。当它死了,它将进行资源清理。当然,如果ninject获得了自己的“盒子”对象并且只保留了对它的弱引用,那么GC可以随时收集它。这意味着您的资源可能会在范围实际结束之前被处理掉。
因此,您需要将scope-id包装在一个对象中(并保留对该对象的引用,而不仅仅是对该值的引用),并且最好还要为确定性资源清理实现INotifyWhenDisposed
。< / p>
提示:Ninject.Extensions.NamedScope
中包含的InCallScope
可能更适合您的用例。
另一种可能的替代方案是每个会话使用ChildKernel
。这类似于每个会话创建一个内核 - 但它不是那么重量级。