2012-01-26 3 views
6

Хорошо, так недавно я читал в ninject, но у меня возникли проблемы с пониманием того, что делает его лучше, почему они ссылаются на DI-страницу «бедного человека» на странице вики. Печально то, я пошел на все свои страницы на вики и до сих пор не понимаю = (Проблемы с пониманием ninject (или только контейнера IOC в целом) по заводской 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 код-меньше линии Я просто не вижу. преимущество, когда вы добавляете/удаляете конструкторы или изменяете реализация конструктора интерфейса, вам придется изменить модуль практически так же, как на фабрике нет? Поэтому мы не видим преимущества здесь.

Тогда я думал, что я мог придумать общую конвенцию фабрика, основанной, как так:

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; 
    } 

Однако это дерьмовое по 2 причинам: 1) Его сильно зависит от именования, 2) Это предполагается в репозитории никогда не будет никаких конструкторов (не верно), и единственным конструктором службы будет соответствующий репо (также не верно). Мне сказали «Эй, вот где вы должны использовать контейнер IoC, здесь было бы здорово!» И, таким образом, мое исследование началось ... но я просто не вижу его, и я не понимаю его ...

Есть ли какой-то способ, который ninject может автоматически разрешать конструкторы класса без специального объявления, отлично подходит для использования на моем общем заводе (я также понимаю, что могу просто сделать это вручную, используя отражение, но это удар производительности, а ninject говорит прямо на своей странице, что они не используют отражение).

Просвещение по этой проблеме и/или показ того, как ее можно использовать на моей фабрике, было бы высоко оценено!

EDIT: Ответ

Так благодаря объяснению ниже я умело, чтобы полностью понять удивительность Ninject и мой общий завод выглядит следующим образом:

public static class EntityServiceFactory 
{ 
    public static TServiceClass GetService<TServiceClass>() 
     where TServiceClass : class 
    { 
     IKernel kernel = new StandardKernel(); 

     return kernel.Get<TServiceClass>(); 
    } 
} 

Довольно удивительным. Все обрабатывается автоматически, так как конкретные классы имеют неявное связывание.

+0

Обычная сломанный запись комментарий: бежать [Инъекции зависимостей в .NET книге мой Mark Seemann] (http.commanning.com/seemann). Я не могу себе представить, что вы не чувствуете уверенности в том, почему и как DI (шаблон) и контейнеры DI в течение недели владеть книгой. –

ответ

7

Преимущества контейнеров IoC растут с размером проекта. Для небольших проектов их выгода по сравнению с «Бедным человеком DI», как ваша фабрика, минимальна. Представьте себе большой проект, в котором тысячи классов, а некоторые службы используются во многих классах. В этом случае вам нужно только сказать, как эти службы будут разрешены. На заводе вам нужно делать это снова и снова для каждого класса.

Пример: Если у вас есть услуга MyService : IMyService и класс A, который требует IMyService, вы должны сообщить Ninject, как он должен разрешать такие типы, как на вашем заводе. Здесь преимущество минимально. Но как только вы начнете проект, вы добавите класс B, который также зависит от IMyService, вам просто нужно сказать Ninject, как разрешить B. Ninject уже знает, как получить IMyService. На заводе, с другой стороны, вам нужно снова определить, как B получает свой IMyService.

Чтобы сделать это еще на один шаг. Вы не должны определять привязки один за другим в большинстве случаев. Вместо этого используйте условную конфигурацию (Ninject.Extension.Conventions). С этим вы можете группировать классы вместе (Services, Repositories, Controllers, Presenters, Views, ....) и настраивать их одинаково. Например. скажите Ninject, что все классы, которые заканчиваются Сервисом, должны быть одиночными и публиковать все их интерфейсы. Таким образом, у вас есть одна конфигурация, и никаких изменений не требуется, когда вы добавляете другую услугу.

Также контейнеры IoC - это не просто фабрики. Их гораздо больше. Например. Жизненный цикл Managment, Перехват, ....

kernel.Bind(
    x => x.FromThisAssembly() 
      .SelectAllClasses() 
      .InNamespace("Services") 
      .BindToAllInterfaces() 
      .Configure(b => b.InSingletonScope())); 
kernel.Bind(
    x => x.FromThisAssembly() 
      .SelectAllClasses() 
      .InNamespace("Repositories") 
      .BindToAllInterfaces()); 
+0

Я вижу (тот же вопрос, что и с другим ответом), так что действительно ninject не поможет мне сделать общую реализацию фабрики? Или каким-то образом автоматически разрешать зависимости без моего объявления? Поскольку он не имеет модуля/фабрики для каждого класса обслуживания. Кроме того, что, если мои репозитории и службы имеют переменное количество инъекций, соглашения не могут быть действительно использованы, не так ли? – SventoryMang

+1

Кажется, вы не понимаете, как работает ninject. Он смотрит на конструктор, а затем пытается получить правильные зависимости от конфигурации. Поэтому классы с различным числом зависимостей можно легко настроить с использованием того же соглашения. –

+0

Хмм я * думаю * Я понимаю сейчас. Поэтому он не может помочь мне для моей родовой фабрики, правильно? Мне все же приходится настраивать инъекции декларативно в какой-то момент, а это значит, что я не могу делать общий ролик здесь. У вас есть пример использования соглашения с переменным числом зависимостей? Извините за то, что здесь так толсто. =. У меня тяжелое время экстраполировать то, что на сайте, на мой собственный сценарий. – SventoryMang

2

Чтобы быть полностью, аналогичным ваш завод код следует читать:

public static class SomeTypeServiceFactory 
{ 
    public static ISomeTypeService GetService() 
    { 
     SomeTypeRepository someTypeRepository = new SomeTypeRepository(); 

     // Somewhere in here I need to figure out if i'm in testing mode 
     // and i have to do this in a scope which is not in the setup of my 
      // unit tests 

     return new SomeTypeService(someTypeRepository); 
    } 

    private static ISomeTypeService GetServiceForTesting() 
    { 
     SomeTypeRepository someTypeRepository = new SomeTypeRepository(); 
     return new SomeTestingTypeService(someTypeRepository); 
    } 
} 

И equilvalent в Ninject будет:

public class WarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<ISomeTypeService>().To<SomeTypeService>(); 
    } 
} 

public class TestingWarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<ISomeTypeService>().To<SomeTestingTypeService>(); 
    } 
} 

Здесь вы можете определить зависимости декларативно, гарантируя, что только различия между вашим тестированием и производственным кодом содержатся на этапе настройки.

Преимущества IoC не в том, что вам не нужно менять модуль каждый раз, когда изменяется интерфейс или конструктор, это факт, что вы можете декларировать объявления декларативно и что вы можете подключать и воспроизводить разные модули для разных цели.

+0

Я вижу, так что действительно ninject не поможет мне сделать общую реализацию фабрики? Или каким-то образом автоматически разрешать зависимости без моего объявления? Поскольку он не имеет модуля/фабрики для каждого класса обслуживания. – SventoryMang

Смежные вопросы