开发者

NInject and thread-safety

I am having problems with the following class in a multi-threaded environment:

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

    public void DoSometh开发者_运维知识库ing()
    {
        /* 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;
    }
}

This is a legacy class which is why I am using property rather than constructor injection.

Sometime when the DoSomething() is called the InjectedBar property is null. In a single-threaded application, everything runs fine.

How can this be occuring and how can I prevent it?

I am using NInject 2.0 without any extensions, although I have copied the KernelContainer from the NInject.Web project.

I have noticed a similar problem occurring in my web services. This problem is extremely intermittent and difficult to replicate.


First of all, let me say that this is wrong on so many levels; the KernelContainer was an infrastructure class kept specifically to work around certain limitations in the ASP.NET WebForms page lifecycle. It was never meant to be used in application code. Using the Ninject kernel (or any DI container) as a service locator is an anti-pattern.

That being said, Ninject itself is definitely thread-safe because it's used to service parallel requests in ASP.NET all the time. Wherever this NullReferenceException is coming from, it's got little if anything to do with Ninject.

I can think of two possibilities:

  1. You have to initialize KernelContainer.Kernel somewhere, and that code might have a race condition. If something tries to use the KernelContainer before the kernel is fully initialized (possible if you use the IKernel.Bind methods instead of loading modules as per the guidance), you'll get errors like this. Or:

  2. It's your IBar implementation itself that has problems, and the NullReferenceException is happening somewhere inside the DoSomething method. You don't actually specify that InjectedBar is null when you get the exception, so that's a legitimate possibility here.

Just to narrow the field of possibilities, I'd eliminate the KernelContainer first. If you absolutely must use Ninject as a service locator due to a poorly-designed legacy architecture, then at least allow it to create the dependencies instead of relying on Inject(this). That is to say, whichever class or classes need to create your Foo, have that class call kernel.Get<Foo>(), and set up your kernel to Bind<Foo>().ToSelf().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜