Мне нужно больше практических примеров Ninject
В прошлом я использовал swiftsuspenders, который является контроллером ActionScript 3 IoC. По сути, первая версия switfsuspender была похожа на ядро Ninject, которое называлось инжектором.
Если я хотел создать инжектор приложения (скажем, с наиболее релевантными сопоставлениями, которые будут использоваться в приложении), я должен был внедрить сам инжектор в классы приложения.
Теперь мне интересно, какова практика использования kernel.get<> среди нескольких классов в приложении. Стоит ли вводить само ядро?
Лично я предпочел бы использовать kernel.inject, но если я могу сделать kernel.inject, я действительно могу ввести зависимости вручную, что, вероятно, лучше (поцелуй).
Контрольные примеры хороши, но они далеки от реальных практических вопросов, поэтому я надеюсь, что вы можете помочь мне прояснить этот момент. Спасибо.
Редактировать: я заметил, что некоторые люди говорят о "корневом контейнере", кажется, что это концепция, которую я ищу. Как мне настроить корневой контейнер и сообщить об этом другим классам приложения?
Пример кода Edit2 (пожалуйста, прости за ошибки, это только для примера):
class SomeClass
{
public SomeClass()
{
Command cmd = new Command();
cmd.execute();
}
}
class SomeOtherClass:ISomeOtherClass
{
public void allright()
{
//right
}
}
class Command
{
ISomeOtherClass dependency;
void execute()
{
dependency.allright();
}
}
Program.Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<SomeClass>().ToSelf().InSingletonScope();
kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>();
SomeClass sc = kernel.Get<SomeClass>();
}
Я еще не проверял это, потому что я все еще борюсь с некоторыми проблемами инициализации, но мой вопрос, как командный класс может знать о SomeOtherClass? Моя текущая гипотеза состоит в том, чтобы внедрить ядро в SomeClass и использовать метод Inject.
2 ответа
Глядя на ваш пример, становится ясно, что SomeClass
не построен с учетом инверсии контроля; наводка на то, что он имеет зависимость от Command
, но контроль над этой зависимостью сохраняется внутри SomeClass
сам. (Command cmd = new Command();
)
Чтобы инвертировать контроль над этой зависимостью, вам нужно иметь способ внедрить эту зависимость в SomeClass. Как указал Remo Gloor, стандартный способ сделать это с помощью Ninject - через конструктор.
Для этого вы можете изменить SomeClass на что-то вроде этого:
class SomeClass
{
private ICommand _command;
public SomeClass(ICommand injectedCommand)
{
_command = injectedCommand;
_command.execute();
}
}
Точно так же вам понадобится ваша команда для объявления ее зависимости:
class Command
{
private ISomeOtherClass _dependency;
public Command(ISomeOtherClass injectedSomeOtherClass)
{
_dependency = injectedSomeOtherClass;
{
void execute()
{
_dependency.allright();
}
}
Затем вы должны зарегистрировать привязку вашей команды в ядре, например:
Program.Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<SomeClass>().ToSelf().InSingletonScope();
kernel.Bind<ICommand>().To<Command>();
kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>();
SomeClass sc = kernel.Get<SomeClass>();
}
Тогда ядро сможет пройти цепочку зависимостей и внедрить их все.
По возможности используйте инъекцию в конструктор и фабрики, когда есть веская причина не создавать экземпляры вместе с объектом, который от них зависит.
kernel.Inject
следует использовать только тогда, когда вы не изменяете создание объекта. Например, веб-форма
kernel.Get
следует использовать ровно один раз в корне композиции (например, Program.Main или MVC3.DependencyResolver) для создания приложения.