Я не эксперт, но я думаю, что могу помочь. И да, это особый тип внедрения зависимостей.
Отказ от ответственности: почти все это было «украдено» из Ninject Wiki
Давайте рассмотрим идею внедрения зависимости, пройдя простой пример. Допустим, вы пишете следующую блокбастерскую игру, в которой благородные воины сражаются за великую славу. Во-первых, нам понадобится оружие, подходящее для вооружения наших воинов.
class Sword
{
public void Hit(string target)
{
Console.WriteLine("Chopped {0} clean in half", target);
}
}
Тогда давайте создадим класс для представления самих наших воинов. Чтобы атаковать своих противников, воину понадобится метод Attack (). Когда этот метод вызывается, он должен использовать свой меч, чтобы поразить своего противника.
class Samurai
{
readonly Sword sword;
public Samurai()
{
this.sword = new Sword();
}
public void Attack(string target)
{
this.sword.Hit(target);
}
}
Теперь мы можем создать нашего самурая и сражаться!
class Program
{
public static void Main()
{
var warrior = new Samurai();
warrior.Attack("the evildoers");
}
}
Как вы можете себе представить, это будет печатать рубленых злодеев чистыми пополам к консоли. Это прекрасно работает, но что если мы захотим вооружить нашего самурая другим оружием? Поскольку Sword создается внутри конструктора класса Samurai, мы должны изменить реализацию класса, чтобы внести это изменение.
Когда класс зависит от конкретной зависимости, говорят, что он тесно связан с этим классом . В этом примере класс самураев тесно связан с классом меча. Когда классы тесно связаны, они не могут быть заменены без изменения их реализации. Чтобы избежать тесной связи классов, мы можем использовать интерфейсы для обеспечения уровня косвенности. Давайте создадим интерфейс для представления оружия в нашей игре.
interface IWeapon
{
void Hit(string target);
}
Затем наш класс Sword может реализовать этот интерфейс:
class Sword : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("Chopped {0} clean in half", target);
}
}
И мы можем изменить наш класс самураев:
class Samurai
{
readonly IWeapon weapon;
public Samurai()
{
this.weapon = new Sword();
}
public void Attack(string target)
{
this.weapon.Hit(target);
}
}
Теперь наш самурай может быть вооружен разным оружием. Но ждать! Меч все еще создается внутри конструктора Самурая. Поскольку нам все еще нужно изменить реализацию Самурая, чтобы дать нашему воину другое оружие, Самурай все еще тесно связан с Мечом.
К счастью, есть простое решение. Вместо того, чтобы создавать Меч из конструктора Самурая, мы можем вместо этого выставить его как параметр конструктора. Также известный как Конструктор Инъекция.
class Samurai
{
readonly IWeapon weapon;
public Samurai(IWeapon weapon)
{
this.weapon = weapon;
}
public void Attack(string target)
{
this.weapon.Hit(target);
}
}
Как отметил Джорджио, существует также инъекция свойств. Это было бы что-то вроде:
class Samurai
{
IWeapon weapon;
public Samurai() { }
public void SetWeapon(IWeapon weapon)
{
this.weapon = weapon;
}
public void Attack(string target)
{
this.weapon.Hit(target);
}
}
Надеюсь это поможет.