C# Ninject-Binding.GetProvider引发NullReferenceException
我正在asp.net web窗体应用程序中使用Ninject的2.2.0.0版,在数百个请求之后,它有时会在Binding类的GetProvider方法中抛出NullReferenceException 堆栈跟踪示例: 只有当我对应用程序进行压力测试时,异常才会发生,并且异常的来源通常是不同的(解析不同的接口) 为了试图理解为什么会出现这个问题,我查看了Ninject源代码,并插入了一些代码行用于调试。我后来确认null对象是绑定类中的ProviderCallback属性 我还将一些代码放在ProviderCallback属性的set运算符中,以了解它是否被设置为null。在运行了一些测试并查看了一些内存转储之后,似乎ProviderCallback属性没有设置为空值,因此我认为该实例是由GC收集的 我还是不明白为什么会这样 非常感谢您的帮助C# Ninject-Binding.GetProvider引发NullReferenceException,c#,asp.net,exception,dependency-injection,ninject,C#,Asp.net,Exception,Dependency Injection,Ninject,我正在asp.net web窗体应用程序中使用Ninject的2.2.0.0版,在数百个请求之后,它有时会在Binding类的GetProvider方法中抛出NullReferenceException 堆栈跟踪示例: 只有当我对应用程序进行压力测试时,异常才会发生,并且异常的来源通常是不同的(解析不同的接口) 为了试图理解为什么会出现这个问题,我查看了Ninject源代码,并插入了一些代码行用于调试。我后来确认null对象是绑定类中的ProviderCallback属性 我还将一些代码放在Pr
编辑:我们升级到Ninject的最新版本只是为了检查异常是否仍然发生,但在对应用程序进行压力测试后,我们得到了相同的异常:我无法告诉您此问题的原因,因为我无法重现这种行为。但是这里有一些你可以采取的步骤来识别问题 正如您所说,问题是由
ProviderCallback
引起的,即null
。这不能由GC引起,因为GC永远不会将null
分配给属性。相反,您将得到一个已处理的异常或其他奇怪的行为。但这种情况的发生还有其他一些原因:
Null
在某个时间被分配,但由于您已经验证了这一点,因此这不是原因BindingConfiguration
BindingConfiguration
构造函数中添加断点来轻松验证。在内核成功配置并开始解析对象之后,不应再调用它
对于第二个问题,请在内核配置之后执行以下操作:
var kernel = your fully configured kernel;
var bindingsField = typeof(KernelBase).GetField("bindings", BindingFlags.NonPublic | BindingFlags.Instance);
var bindings = bindingsField.GetValue(kernel) as IEnumerable<KeyValuePair<Type, ICollection<IBinding>>>;
foreach (var bindingsEntry in bindings
.Where(bindingsEntry => bindingsEntry.Value
.Any(binding => binding.BindingConfiguration.ProviderCallback == null)))
{
throw new Exception(string.Format("No Provider callback defined for {0}.", bindingsEntry.Key));
}
var kernel=完全配置的内核;
var bindingsField=typeof(KernelBase).GetField(“bindings”,BindingFlags.NonPublic | BindingFlags.Instance);
var bindings=bindingsField.GetValue(内核)作为IEnumerable;
绑定中的foreach(var bindingsEntry
.Where(bindingsEntry=>bindingsEntry.Value
.Any(binding=>binding.BindingConfiguration.ProviderCallback==null)))
{
抛出新异常(string.Format(“没有为{0}定义提供程序回调,bindingsEntry.Key));
}
您应该对此进行报告。NullReferenceException始终表示抛出它的代码中存在错误。请尝试更新到最新的Ninject版本。Hi Remo。很抱歉回复得太晚,但我想看看你提供的任何条件是否属实。第二次或第三次都没有发生。事实证明,这种情况很难重现,因为只有每100个对aspx页面的请求才会发生一次。我看到的一件奇怪的事情是内存转储中的第二个StandardKernel,但我无法确定它是在哪里创建的(!refs和!gcroot只向一个庞大的对象数组返回一个根,这些对象似乎是appdomain的静态成员-我仍然不明白为什么)。你不能通过在内核的构造函数中添加断点来找出它是在哪里创建的吗?Remo,我找到了创建它的原因。在Ninject的版本3中,现在有一个Ninject.Web名称空间的依赖项,该名称空间正在Ninject.Web.KernelContainer中创建一个标准内核隐式。我现在回到我的原始版本。我不知道下一步该去哪里。让我告诉你,我们还得到了一些罕见的ActivationException,一旦开始发生,它们将继续抛出,直到我们重新启动应用程序池。我认为这些问题可能是相关的。这发生在版本2.2中,我也能够在版本3中获得罕见的ActivationException(在数百个请求之后),因此当前状态为:1。没有ProviderCallback最初为空。2.以后不会创建新的BindingConfiguration。3.以后不会为ProviderCallback分配任何内容。4.只使用一个内核。在这种情况下,我看不出这怎么会发生。你能创建一个简单的解决方案来演示这个问题吗?@TiagoMargalho感谢你的调查。我强烈建议不要在第一次解析对象后进行任何绑定或重新绑定,因为即使多线程问题得到解决,结果也是不可预测的。例如,如果存在具有非瞬态范围的对象,则仍然可以获取以前实现的实例。尝试使用RRR模式: