Eric
Eric

Reputation: 343

Ninject: GetAll instances that inherit from the same abstract class

Is it possible for Ninject to get all instances that inherit from a specific Abstract Class? For example, I have the following Abstract Class.

public abstract class MyAbstractClass { }

Then I have the following two derived classes that both inherit from the same abstract class.

public class MyDerivedClass1 : MyAbstractClass { }

public class MyDerivedClass2 : MyAbstractClass { }

Now I am going to bind both derived classes with the Kernel because I want them to be in singleton scope.

_kernel = new StandardKernel();
_kernel.Bind<MyDerivedClass1>().ToSelf().InSingletonScope();
_kernel.Bind<MyDerivedClass2>().ToSelf().InSingletonScope();

I know the Kernel can return me an instance like the following.

_kernel.Get<MyDerivedClass1>();

Is there a way to get all of the classes that inherit from MyAbstractClass? I tried the following without success.

IEnumerable<MyAbstractClass> items = kernel.GetAll<MyAbstractClass>();

The hope was that the above GetAll() method would return a list of two instances, one would be MyDerivedClass1 and the second would be MyDerivedClass2.

Upvotes: 0

Views: 1728

Answers (3)

Michael Snytko
Michael Snytko

Reputation: 337

So if you need to have a singleton inherited from abstract class and to use it via GetAll or Get, it works like this:

public abstract class Test
{
    public string Name;
    public Test(string s)
    {
        Name = s;
    }
}

public class T1 : Test
{
    public T1() : base("T1")
    {
    }
}

public class T2 : Test
{
    public T2() : base("T2")
    {
    }
}

Then:

    static StandardKernel kernel;
    static void Main(string[] args)
    {
        kernel = new StandardKernel(new LoadModule());    

        var tests = kernel.GetAll<Test>();
        tests.ToList().ForEach(c => Console.WriteLine(c.Name));
        Console.WriteLine();

        Console.WriteLine(GetByType<T1>().Name);
        var z = GetByType<T1>();
        z.Name = "abc";           
        Console.WriteLine(z.Name);
        Console.WriteLine(GetByType<T1>().Name);

        Console.WriteLine();

        Console.WriteLine(GetByType<T2>().Name);
        var za = GetByType<T2>();
        za.Name = "abc";
        Console.WriteLine(za.Name);
        Console.WriteLine(GetByType<T2>().Name);

        Console.WriteLine();

        tests = kernel.GetAll<Test>();
        tests.ToList().ForEach(c => Console.WriteLine(c.Name));
        Console.WriteLine();

        Console.ReadKey();



    }

    static public T GetByType<T>()
    {
        return kernel.Get<T>();
    }

    public class LoadModule : NinjectModule
    {
        public override void Load()
        {    
            this.Bind<Test, T1>().To<T1>().InSingletonScope();
            this.Bind<Test>().To<T2>();

        }
    }

Output as expected:

    T1
    T2


    T1
    abc
    abc

    T2
    abc
    T2

    abc
    T2

Upvotes: 0

BatteryBackupUnit
BatteryBackupUnit

Reputation: 13233

instead of creating two bindings, the second one with a "redirect" to the first, what you can also do is:

_kernel.Bind<MyAbstractClass, MyDerivedClass1>()
       .To<MyDerivedClass1>().InSingletonScope();
_kernel.Bind<MyAbstractClass, MyDerivedClass2>()
       .To<MyDerivedClass1>().InSingletonScope();

This expresses the intention more clearly.

Upvotes: 2

xenolightning
xenolightning

Reputation: 4230

Currently you're binding only to the implementation type, not the base class type, with ToSelf. It's effectively calling _kernel.Bind<MyDerivedClass1>().To<MyDerivedClass1>()

To bind the implementation types to the base type use:

_kernel = new StandardKernel();
_kernel.Bind<MyAbstractClass>().To<MyDerivedClass1>().InSingletonScope();
_kernel.Bind<MyAbstractClass>().To<MyDerivedClass2>().InSingletonScope();

//returns both
var allImplementations = _kernel.GetAll<MyAbstractClass>();

EDIT: Multiple bindings to singleton.

_kernel = new StandardKernel();
_kernel.Bind<MyDerivedClass1>().ToSelf().InSingletonScope();
_kernel.Bind<MyDerivedClass2>().ToSelf().InSingletonScope();

_kernel.Bind<MyAbstractClass>().ToMethod(x => _kernel.Get<MyDerivedClass1>());
_kernel.Bind<MyAbstractClass>().ToMethod(x => _kernel.Get<MyDerivedClass2>());

Upvotes: 3

Related Questions