Search code examples
c#.netninjectninject-extensions

How to properly use Ninject's NamedScope extension?


I have a pattern that comes up all the time when I'm working. I am almost exclusively a web developer, and Ninject's InRequestScope handles 99% of my needs.

Here's the pattern:

// abstractions

interface IFoo {
    void FooMe();
    int GetSomeValue();
}

interface IBar {
    void BarMe();
}

interface IFooBar {
    void FooAndBar();
}

// concrete classes

class Foo : IFoo {
    public void FooMe() { Console.WriteLine("I have fooed"); }
    public void GetSomeValue() { return 123; }
}

class Bar : IBar {
    private readonly IFoo _Foo;

    public Bar(IFoo foo) { _Foo = foo; }

    public void BarMe() { Console.WriteLine("Bar: {0}", _Foo.GetSomeValue()); }
}

class FooBar : IFooBar {
    private readonly IFoo _Foo;
    private readonly IBar _Bar;

    public Bar(IFoo foo, IBar bar) { _Foo = foo; _Bar = bar; }
    public void FooAndBar() {
        _Foo.FooMe();
        _Bar.BarMe();
    }
}

// bindings
kernel.Bind<IFoo>().To<Foo>();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IFooBar>().To<FooBar>();

What I want to do is set it up such that every time I kernel.Get<IFooBar> it creates exactly one Foo and injects it into the constructors of both Bar and FooBar.

I've experimented with this off and on using the Named Scope extension, but I've never been able to get it to work.

What is the proper binding syntax for this?


Solution

  • so what you've got to do is define some name:

    const string FooBarScopeName = "FooBarScope";
    

    and then define the scope:

    kernel.Bind<IFooBar>().To<FooBar>()
          .DefinesNamedScope(FooBarScopeName);
    

    and bind the Foo in the named scope (the name must match!):

    kernel.Bind<IFoo>().To<Foo>();
          .InNamedScope(FooBarScope);
    

    Alternative:

    There's also InCallScope() which can be used if there's one kernel.Get() for each time a IFooBar is created. In that case, simply do:

    kernel.Bind<IFoo>().To<Foo>().InCallScope();