Внедрение зависимостей на первый взгляд может показаться запутанным, но на самом деле все довольно просто.
«Контейнер» внедрения зависимостей - это в основном универсальная фабрика с различными функциями управления временем жизни объектов. В частности, Ninject использует синтаксис kernel.Bind()
для настройки этой фабрики. Когда вы говорите kernel.Bind<DbEntities>().ToSelf()
, это означает, что Ninject будет создавать экземпляр связанного типа (в данном случае DbEntities) всякий раз, когда запрашивается этот тип. Этот запрос обычно выглядит так:
var entities = kernel.Get<DbEntities>(); // Note: don't do this, just an example
По сути, это и есть инъекция зависимости. Универсальная фабрика, которая может создавать экземпляры произвольных типов.
Однако в этом есть нечто гораздо большее. Одна приятная особенность внедрения зависимостей заключается в том, что он также будет создавать экземпляры любых зависимых типов в процессе. Итак, предположим, у вас есть контроллер, и этот контроллер зависит от DbEntities. Хорошо, когда контроллер создается в DI Framework, он также создает экземпляры зависимых DbEntities. Смотрите код ниже. Когда создается экземпляр MyController, создаются экземпляры DbEntities автоматически (при условии, что вы связали класс DbEntities с self в конфигурации DI)
var controller = kernel.Get<MyController>();
public class MyController : Controller {
private DbEntities _entities;
public MyController(DbEntities entities) {
_entities = entities;
}
}
Это рекурсивно. Любой класс, для которого создается экземпляр, который имеет любые объекты, от которых он сам может зависеть, также получает экземпляр, и так далее, и так далее, пока, наконец, у всего не будет того, что ему нужно для своей работы.
Теперь, что самое замечательное в MVC, это то, что он имеет встроенный способ автоматического использования любого DI-контейнера. Вам не нужно вызывать kernel.Get
, потому что инфраструктура делает это за вас, когда создает контроллеры при поступлении запроса. Эта функция называется IDependencyResolver
и представляет собой интерфейс, который использует инфраструктура MVC, чтобы разрешить сторонний DI контейнеры для использования каркасом.
Если вы устанавливаете Ninject с помощью пакета Nuget Ninject.MVC3, он автоматически настроит все это для вас, и вам нужно только добавить свои привязки в раздел RegisterServices () в NinjectMVC3.cs
Это намного больше, чем это, но это должно дать вам базовое понимание. Внедрение зависимостей позволяет вам забыть о деталях управления созданием и уничтожением объектов, вы просто указываете в конструкторе, какие зависимости вам нужны, и, предполагая, что у вас есть привязки к ним в вашей конфигурации, MVC позаботится о их создании и уничтожении для вы. Вы просто используете их.
EDIT:
Для ясности, я не рекомендую вам использовать примеры, которые я привел выше. Они просто простые иллюстрации того, как работает DI. В частности, синтаксис Get () известен как «Расположение службы» и считается плохим. Однако, в конечном счете, некоторый код, который где-то должен вызывать Get (), просто скрыт глубоко в фреймворке.
Как упоминает Адам, связывание напрямую с контекстом сущностей данных не является хорошей идеей, и в конечном итоге вам следует перейти к использованию подхода, основанного на интерфейсе.