在我的MVC3项目中,我已经在InRequestScope的基础上将我的内核设置为Ninject Entityframework上下文,这非常有效,但我有一个后台运行器可以进行一些工作流管理。
它每隔5分钟激活一个新线程并且我将我的依赖项Ninject到此线程中,如果我将范围更改为InThreadScipe,则会触发Dispose方法,但如果我将其更改回InRequestScope,则Dispose方法将不会触发。
如果InRequestScope不可用,是否有退回InThreadScope的方法?
更新:刚刚获得了这个问题的upvote,为什么不用一些额外的信息更新它。我认为Ninjects处理生命时间的方式有点过时了。其他IoC的子容器是Transient注册的对象,它们存放在整个子容器中,并在子容器处理时被丢弃。这是一种更简单的方法,例如将Web API与上述场景中的自定义工作程序相结合。
答案 0 :(得分:14)
有一个InScope
方法,您可以使用该方法指定自定义范围规则。
InRequestScope的实施目前正在从2.2-2.4进行更改。
请转到您的版本来源,查看InRequestScope
和InThreadScope
的impl并创建一个汞合金(然后您可以将其作为一种扩展方法与另一个{{1}一起插入方法。
看起来(在将其提取到扩展方法之前),例如:
InXXXScope
另一种方法是使用适当的约束(例如Bind<X>.To<T>().InScope( ctx => ScopeContext.Request(ctx) ?? ScopeContext.Thread(ctx))
)创建两个Bind
,以根据contextual binding自定义范围。
答案 1 :(得分:6)
感谢Ruben,我找到了一个解决方案,但是在他的伪代码中偷偷摸摸出了一个小虫子,因为它是星期一而我累了我没有立刻看到它:D
StandardScopeCallbacks.Request
是代表还是
StandardScopeCallbacks.Request ?? StandardScopeCallbacks.Thread
将始终返回左侧,因为委托永远不会为空。
有两种方法可以正确执行此操作,
public static IBindingWhenInNamedWithOrOnSyntax<T> InRequestFallbackScope<T>(this IBindingWhenInNamedWithOrOnSyntax<T> binding)
{
Func<IContext, object> fallbackCallback = ctx => StandardScopeCallbacks.Request(ctx) ?? StandardScopeCallbacks.Thread(ctx);
binding.Binding.ScopeCallback = fallbackCallback;
return binding;
}
.InScope(ctx => StandardScopeCallbacks.Request(ctx) ?? StandardScopeCallbacks.Thread(ctx))
答案 2 :(得分:2)
这是我编写的第一个请求范围和线程作为后备。
public static class NinjectBindingExtensions
{
private static bool IsRequestPresent()
{
try
{
return HttpContext.Current != null;
}
catch
{
return false;
}
}
private static object GetScope(IContext ctx)
{
// note: this is a copy of the private method of Ninject.Web.Common.RequestScopeExtensionMethod#GetScope
return ctx.Kernel.Components.GetAll<INinjectHttpApplicationPlugin>().Select(c => c.RequestScope).FirstOrDefault(s => s != null);
}
public static IBindingWhenInNamedWithOrOnSyntax<T> InRequestFallbackScope<T>(this IBindingWhenInNamedWithOrOnSyntax<T> binding)
{
Func<IContext, object> fallbackCallback = ctx => IsRequestPresent() ? GetScope(ctx) : StandardScopeCallbacks.Thread(ctx);
binding.BindingConfiguration.ScopeCallback = fallbackCallback;
return binding;
}
}
如果您处于线程场景中,请确保调用_kernel.Components.Get<ICache>().Clear(Thread.CurrentThread);
来触发您在此范围内加载的对象(可能是现有的)Dispose()( - &gt; Thread.CurrentThread)。