Используя Ninject, могу ли я создать экземпляр из интерфейса, не раскрывая мой конкретный класс? - PullRequest
10 голосов
/ 15 марта 2011

Примеры, которые я видел до сих пор, выглядят так:

Напишите свой код следующим образом ...

public class Samurai {
  public IWeapon Weapon { get; private set; }
  public Samurai(IWeapon weapon) {
    Weapon = weapon;
  }
}

И Ninject может сопоставить интерфейс с конкретным типом следующим образом...

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

Поэтому, когда я говорю var samurai = kernel.Get<Samurai>(); в моем объекте самурая, мое IWeapon автоматически становится мечом.

Это круто, но что если я хочу только ISword без самураяа конкретный меч помечен как внутренний?

В настоящее время я использую самодельный решатель зависимостей, где я могу сказать var sword = DependencyResolver.Current.Resolve<ISword>();, и он возвращает мне меч, брошенный как ISword.Мои конкретные классы помечены как внутренние, поэтому разработчик должен пройти через мой решатель зависимостей, чтобы создать экземпляр.Есть ли в Ninject что-нибудь похожее на это?

И дополнительный вопрос: я украшаю свои интерфейсы с помощью специального атрибута "DefaultConcreteType", который мой преобразователь зависимостей может использовать, если не существует сопоставления.У Ninject есть что-нибудь подобное?

Спасибо

Ответы [ 3 ]

15 голосов
/ 15 марта 2011

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

var sword = kernel.Get<ISword>();

И это даст вам конкретный Sword объект.Вы также можете сделать намного больше с системой привязки.Вы могли бы даже Bind<ISword>().ToMethod(MySwordFactory); и написать метод для получения Swords на основе запрашивающего контекста.

Еще одна вещь, которую вы можете сделать, это изменить способ привязки работ, основанный на типе, в который он вводится.Например, вы можете выставить свойство в пользовательском классе, например, так:

public class MyClass {
    [Inject]
    public ISword Sword { get; set; }
}

И затем вы можете привязать к конкретной реализации ISword на основе MyClass:

Bind<ISword>().To<Sword>().WhenInjectedInto<MyClass>();

Естьнамного больше вариантов, но это должно дать вам приблизительный обзор.

0 голосов
/ 15 марта 2011

Это не дает прямого ответа на ваш вопрос, но я знаю, что с Unity вы можете сделать это, используя файлы конфигурации, а не связывая свои зависимости в коде. К сожалению, Ninject не поддерживает файлы конфигурации.

Ваша альтернатива этому - использовать неуниверсальные перегрузки:

Bind(typeof(IWeapon)).To(typeof(Sword));

И тогда вы сможете сделать что-то вроде:

Bind(typeof(IWeapon)).To(Type.GetType("MyNamespace.MyInternalSword"))

но это ужасно, если вы спросите меня ...

0 голосов
/ 15 марта 2011

Я бы порекомендовал использовать абстрактную фабрику, которая может создавать ISword с. Это имеет преимущество перед DependencyResolver в том, что типы, которые он может создавать, ограничены (до ISword).

Ваша абстрактная фабрика должна быть общедоступной, как и ваш DependencyResolver.

...