Binding Ninject to the InInjectedInto extension method

I feel like I'm missing something obvious. I read a few related questions here, and I read the updated Ninject context binding page, but alas, it still doesn't work.

I am trying to modify an outdated application that used a factory pattern to use Ninject.

I have 1 interface (IInterface) implemented by two classes (ClassB and ClassC). IInterface has a boot method. In the ClassB boot method, it starts ClassC and then executes its boot method.

Basically, the ClassA program thread creates ClassB and executes the load method. In the load method, ClassB creates a ClassC that does some work.

My bindings are configured like this ...

Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>(); Bind<IInterface>().To<ClassB>().WhenInjectedInto<ClassA>(); 

When this is done, it fails in the ClassB boot method with this error ...

Error activating IInterface There are no corresponding bindings, and the type is not self-switching.

If I try the following ...

 Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>(); Bind<IInterface>().To<ClassB>(); 

It makes an infinite loop and never creates a ClassC.

EDIT I simplified this into a unit test that passes, but doesn't give me the results I want ...

 [TestClass] public class NinjectTestFixture { private interface IDoSomething { void SaySomething(); } private class ClassA : IDoSomething { public void SaySomething() { Console.WriteLine("Hello from Class A"); } } private class ClassB : IDoSomething { private IKernel _Kernel; public ClassB(IKernel kernel) { _Kernel = kernel; } public void SaySomething() { Console.WriteLine("Hello from Class B"); var x = _Kernel.Get<IDoSomething>(); x.SaySomething(); } } private class ClassC { private IKernel _Kernel; public ClassC(IKernel kernel) { _Kernel = kernel; } public void SaySomething() { Console.WriteLine("Hello from Class C"); var x = _Kernel.Get<IDoSomething>(); x.SaySomething(); } } [TestMethod] public void TestMethod1() { var kernel = new StandardKernel(); kernel.Bind<IDoSomething>().To<ClassA>(); kernel.Bind<IDoSomething>().To<ClassB>().WhenInjectedInto<ClassC>(); kernel.Bind<ClassC>().ToSelf(); var x = kernel.Get<ClassC>(); x.SaySomething(); } 

Exit: Greetings from class C Greetings from class A

But I want: Greetings from class C Greetings from class B Greetings from class A

thanks

+6
source share
1 answer

You do not type in ClassC. You pass the kernel and resolve IDoSomething directly from it. There is a big difference.

Do not pass the kernel as a parameter - this is not Dependency Injection, this is the location of the service (a good article about the difference: Service Locator is Anti-Pattern ).

Modify ClassC as follows:

 private class ClassC { private IDoSomething _doSomething; public ClassC(IDoSomething doSomething) { _doSomething = doSomething; } public void SaySomething() { Console.WriteLine("Hello from Class C"); //var x = _Kernel.Get<IDoSomething>(); _doSomething.SaySomething(); } } 

You must also make the same changes to ClassA and ClassB (pass the type / interface you want to allow, not the kernel).

+6
source

Source: https://habr.com/ru/post/897544/