Reputation: 343
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
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
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
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