NInject和线程安全

时间:2010-05-31 06:27:41

标签: multithreading ninject

我在多线程环境中遇到以下类的问题:

public class Foo
{
    [Inject]
    public IBar InjectedBar { get; set; }
    public bool NonInjectedProp { get; set; }

    public void DoSomething()
    {
        /* The following line is causing a null-reference exception */
        InjectedBar.DoSomething();
    }

    public Foo(bool nonInjectedProp)
    {
         /* This line should inject the InjectedBar property */
         KernelContainer.Inject(this);
         NonInjectedProp = nonInjectedProp;
    }
}

这是一个遗留类,这就是我使用属性而不是构造函数注入的原因。

有时,当调用DoSomething()时,InjectedBar属性为null。在单线程应用程序中,一切运行正常。

如何发生这种情况,我该如何预防?

虽然我已经从NInject.Web项目中复制了KernelContainer,但我使用的是没有任何扩展的NInject 2.0。

我注意到我的网络服务中出现了类似的问题。这个问题极其间歇,难以复制。

1 个答案:

答案 0 :(得分:2)

首先,我要说这在很多层面都是错误的; KernelContainer是一个基本上 的基础结构类,可以解决ASP.NET WebForms页面生命周期中的某些限制。它从未打算用在应用程序代码中。使用Ninject内核(或任何DI容器)作为服务定位器is an anti-pattern

话虽这么说,Ninject本身绝对是线程安全的,因为它一直用于在ASP.NET中为并行请求提供服务。无论这个NullReferenceException来自哪里,它与Ninject几乎无关。

我可以想到两种可能性:

  1. 您必须在某处初始化KernelContainer.Kernel,并且 代码可能具有竞争条件。如果在内核完全初始化之前尝试使用KernelContainer(如果您使用IKernel.Bind方法而不是按照指导加载模块,则可能),您将收到这样的错误。或者:

  2. 这是您的IBar实施本身存在问题,而NullReferenceException正在DoSomething方法内的某处发生。当你得到异常时,你实际上没有指定InjectedBarnull,所以这是合法的可能性。

  3. 为了缩小可能性范围,我首先要消除KernelContainer。如果您绝对必须使用Ninject作为服务定位器,因为遗留架构设计不佳,那么至少允许它创建依赖关系而不是依赖Inject(this)。也就是说,无论哪个类或类需要创建您的Foo,让 类调用kernel.Get<Foo>(),并将内核设置为{ {1}}。