使用WhenInjectedInto扩展方法绑定Ninject

oli*_*iwa 6 c# dependency-injection ninject ninject-2

我觉得我错过了一些明显的东西.我在这里阅读了几个相关的问题,我已经在Ninject的维基上阅读了更新的上下文绑定页面,但是它仍然不起作用.

我正在尝试改进使用工厂模式的遗留应用程序来使用Ninject.

我有1个接口(IInterface)由2个类(ClassB和ClassC)实现.IInterface有一个加载方法.在ClassB的加载方法中,它实例化ClassC然后执行它的加载方法.

基本上程序流是ClassA创建ClassB并执行load方法.在load方法中,ClassB创建了一些可以完成某些工作的ClassC.

我的绑定设置如此......

Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>();
Bind<IInterface>().To<ClassB>().WhenInjectedInto<ClassA>();
Run Code Online (Sandbox Code Playgroud)

当它运行时,它在ClassB的加载方法中失败并出现此错误...

激活IInterface时出错没有匹配的绑定可用,并且该类型不可自我绑定.

如果我尝试以下......

Bind<IInterface>().To<ClassC>().WhenInjectedInto<ClassB>();
Bind<IInterface>().To<ClassB>();
Run Code Online (Sandbox Code Playgroud)

它无限循环,永远不会创建ClassC.

编辑 我已将其简化为单元测试,但未给出我想要的结果...

[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();
    }
Run Code Online (Sandbox Code Playgroud)

输出为:来自Class A的Class C Hello的Hello

但是我想要:来自Class C的Class C Hello的C类Hello

谢谢

Phi*_*ler 6

没有注入ClassC.您正在传递内核并直接从中解析IDoSomething.有一个很大的不同.

不要将内核作为参数传递 - 这样做不是依赖注入,而是服务位置(关于差异的好文章:服务定位器是反模式).

将ClassC更改为:

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();          
    }     
} 
Run Code Online (Sandbox Code Playgroud)

您还应该对ClassA和ClassB进行相同的更改(传递要解析的类型/接口,而不是内核).