Хорошо, так что недавно я читал в ninject, но у меня проблемы с пониманием того, что делает его лучше, чем то, почему они назвали DI "бедным человеком" на странице вики. Самое печальное, что я просмотрел все их страницы в вики и все еще не понял =(.
Обычно я оборачиваю свои сервисные классы в паттерн фабрики, который обрабатывает DI следующим образом:
public static class SomeTypeServiceFactory
{
public static SomeTypeService GetService()
{
SomeTypeRepository someTypeRepository = new SomeTypeRepository();
return = new SomeTypeService(someTypeRepository);
}
}
Что мне кажется очень похожим на модули:
public class WarriorModule : NinjectModule {
public override void Load() {
Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf().InSingletonScope();
}
}
Где каждый класс имеет свой модуль, и вы привязываете его конструктор к конкретной реализации. Хотя код ninject на 1 строку меньше, я просто не вижу преимущества, в любое время, когда вы добавляете/удаляете конструкторы или изменяете реализацию конструктора интерфейса, вам придется изменить модуль практически так же, как и фабрику, нет? Так что не вижу здесь преимущества.
Затем я подумал, что мог бы придумать фабрику, основанную на общих соглашениях, например, так:
public static TServiceClass GetService<TServiceClass>()
where TServiceClass : class
{
TServiceClass serviceClass = null;
string repositoryName = typeof(TServiceClass).ToString().Replace("Service", "Repository");
Type repositoryType = Type.GetType(repositoryName);
if (repositoryType != null)
{
object repository = Activator.CreateInstance(repositoryType);
serviceClass = (TServiceClass)Activator.CreateInstance(typeof (TServiceClass), new[]{repository});
}
return serviceClass;
}
Однако, это плохо по двум причинам: 1) Она сильно зависит от соглашения об именовании, 2) Она предполагает, что у хранилища никогда не будет никаких конструкторов (это не так) и единственным конструктором сервиса будет соответствующее репо (тоже не так). Мне сказали "эй, здесь нужно использовать IoC-контейнер, это было бы здорово!" И таким образом началось мое исследование... но я просто не вижу и не могу понять этого...
Есть ли какой-то способ, которым ninject может автоматически разрешать конструкторы класса без конкретного объявления, что было бы здорово использовать в моей общей фабрике (я также понимаю, что я мог бы сделать это вручную, используя отражение, но это падение производительности, а ninject прямо на своей странице говорит, что не использует отражение).
Просветите по этому вопросу и/или покажите, как это можно использовать в моей общей фабрике, буду очень признателен!
EDIT: Ответ
Итак, благодаря объяснению ниже я смог полностью понять всю крутость ninject и моя generic factory выглядит так:
public static class EntityServiceFactory
{
public static TServiceClass GetService<TServiceClass>()
where TServiceClass : class
{
IKernel kernel = new StandardKernel();
return kernel.Get<TServiceClass>();
}
}
Довольно круто. Все обрабатывается автоматически, поскольку конкретные классы имеют неявное связывание.