Исключить привязку с помощью метода расширения WhenInjectedInto - PullRequest
6 голосов
/ 18 сентября 2011

Я чувствую, что упускаю что-то очевидное.Я прочитал несколько связанных вопросов здесь и прочитал обновленную страницу контекстных привязок в вики Ninject, но, увы, она все еще не работает.

Я пытаюсь дооснастить устаревшее приложение, которое использовало фабричный шаблониспользовать Ninject.

У меня есть 1 интерфейс (IInterface), реализованный 2 классами (ClassB и ClassC).У IInterface есть метод загрузки.В методе загрузки ClassB он создает экземпляр ClassC, а затем выполняет свой метод загрузки.

В основном поток программы ClassA создает ClassB и выполняет метод загрузки.В методе загрузки ClassB создает ClassC, который выполняет некоторую работу.

Мои привязки настроены так ...

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

При выполнении этого происходит сбой в методе загрузки ClassB с этой ошибкой..

Ошибка активации IInterface Соответствующие привязки недоступны, а тип не является самосвязываемым.

Если я попытаюсь выполнить следующее ...

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

Выполняетсябесконечный цикл и никогда не создает ClassC.

EDIT Я упростил это в модульном тесте, который проходит, но не дает мне желаемых результатов ...

[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();
    }

Вывод: Привет из класса C Привет из класса A

Но я хочу: Привет из класса C Привет из класса B Привет из класса A

Спасибо

1 Ответ

6 голосов
/ 18 сентября 2011

Вы не для инъекций в 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();          
    }     
} 

Вы должны также внести те же изменения в ClassA и ClassB (передать тип / интерфейс, который вы хотите разрешить, а не ядро).

...