Где происходит волшебство, когда контроллер создает экземпляр правильной реализации интерфейса в веб-API DI?

Мне кажется, что где-то кролика из шляпы вытаскивают, когда дело касается DI в Web API Controllers.

Я понимаю, что: 0) Контроллер в проекте веб-API может вызываться с различными классами, которые должны быть созданы, каждый из которых реализует интерфейс, от которого зависит Контроллер. например, с этим кодом контроллера:

private readonly IDepartmentRepository _deptsRepository;

public DepartmentsController(IDepartmentRepository deptsRepository)
{
    if (deptsRepository == null)
    {
        throw new ArgumentNullException("deptsRepository is null");
    }
    _deptsRepository = deptsRepository;
}

..."deptsRepository" может быть классом, который реализует IDepartmentRepository и извлекает тестовые данные, ИЛИ это может быть класс, который реализует IDepartmentRepository и извлекает производственные данные, ИЛИ (и т. д.)

1) Веб-API решает, какой контроллер вызывается на основе URI, который вызывает клиент, и этот веб-API решает, какой метод в этом контроллере вызывается на основе его типа (GET, POST) и т. д. и какие аргументы, если таковые имеются, прошел с ним.

2) Castle Windsor перехватывает это автоматическое управление контроллерами с помощью собственного заменяющего механизма маршрутизации.

Чего я не понимаю, так это того, что разработчик внедряет конкретный класс, который реализует интерфейс, ожидаемый контроллером. IOW, если я хочу запустить класс, который извлекает тестовые данные, где мне добавить код, чтобы указать это? Я бы подумал, что это где-то в Global.asax.cs, что-то вроде (псевдокод):

// Use test data for now
DeptsControllerClass = TestDataClass;
//DeptsControllerClass = ProductionDataClass;

IOW, где можно указать: «На этот раз я хочу, чтобы вы внедрили ЭТОТ конкретный класс, который реализует требуемый интерфейс»?


person B. Clay Shannon    schedule 30.12.2013    source источник


Ответы (1)


Как вы написали в пункте 1, маршрутизация и IoC — это две разные вещи.

Как только механизм маршрутизации выясняет, какой контроллер должен быть вызван, будет вызвана «фабрика контроллеров».

Фреймворк WebApi позволяет подключить собственную фабрику следующим образом:

GlobalConfiguration.Configuration.Services.Replace(
    typeof(IHttpControllerActivator),
    new WindsorCompositionRoot(this.container));

Подробнее читайте в сообщении Марка Симанна о сантехнике webapi&windsor.

Какой конкрет будет использоваться для удовлетворения данной зависимости интерфейса, это зависит от ioc, который вы решите использовать на своей фабрике, как указано выше. Используя Windsor, вы можете/должны связать интерфейс и бетон в установщиках.

Позвольте мне попытаться резюмировать весь процесс 1) Настроить маршрутизацию, чтобы связать URL-адрес и контроллер 2) создать контейнер и зарегистрировать все компоненты с помощью установщиков 3) заменить фабрику контроллера по умолчанию на фабрику, работающую с вашим любимым контейнером ioc ( Виндзор, я полагаю :-)) 4) Наслаждайтесь волшебством.

Все эти шаги произошли в Application_start в Global.asax.

person Crixo    schedule 30.12.2013
comment
Хорошо; Я думаю, что у меня может быть весь код, который мне нужен, я просто не знаю точно, как его подключить; в частности, что мне нужно сделать, чтобы связать мой репозиторий/контроллер с моим классом DepartmentProviderInstaller здесь: stackoverflow.com/questions/20843810/ - person B. Clay Shannon; 31.12.2013
comment
IOW, Как связать интерфейс и бетон в установщиках? - person B. Clay Shannon; 31.12.2013
comment
Для IWindsorInstaller требуется пустая установка (контейнер IWindsorContainer, хранилище IConfigurationStore), поэтому в методе Install у вас есть контейнер, поэтому вам просто нужно зарегистрировать компонент. Простейшая регистрация — container.Register(Component.For‹ IDepartmentRepository›().ImplementedBy‹YourDepartmentRepository›()); - person Crixo; 31.12.2013