StructureMap 2.6.1 и ASP.NET MVC 2 Вопросы (от начинающего в DI) - PullRequest
1 голос
/ 11 ноября 2010

В разговоре с @Aaronaught в другом потоке я начал преобразовывать свое приложение для использования Dependency Injection и шаблонов репозитория, но я немного застрял.Я думаю, что я получил большую часть материала и потока шаблонов, но я застрял при реализации StructureMap в ASP.NET MVC 2. Примеры, которые я читал, устарели с последней версией Structure Map, которую яЯ использую (2.6.1).

Я надеюсь, что кто-то может заполнить пробелы на основе кода, который я вставил ниже:

public static class Bootstrapper {
    public static void Configure() {
        ObjectFactory.Configure(x => {
            x.For<DataContext>().Add(new DataContext());
        });
    }
}

С этим я могу получить экземплярDataContext из моего контроллера (ов) с:

protected DataContext dc = ObjectFactory.GetInstance<DataContext>();

Я знаю, что это неправильно, но я не понимаю, как этого избежать.Продолжаем, вот фабрика контроллеров:

public class StructureMapControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(
        RequestContext rc,
        Type ct) {
        return (ObjectFactory.GetInstance(ct) as Controller);
    }
}

Я точно не понимаю, что это делает, но это в примерах, поэтому я копирую это.Кто-нибудь может мне это объяснить?

Теперь, насколько я понимаю, должны быть реестры, которые, если я правильно понимаю, глобализируют экземпляры объектов, такие как DataContext.Это верно?Если да, то как мне написать реестр для StructureMap 2.6.1?Пример кода, который я видел, кажется устаревшим, потому что, когда я пишу его, у меня нет тех же опций, доступных для меня (через IntelliSense), поэтому я не уверен, как его написать ...

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

PS Мой опыт работы с инжекцией зависимостей и репозиториями составляет всего около 8 часов.1022 *

Прочитав превосходное объяснение @ Pure ниже и просмотрев видео tekpub, на которое он ссылался в подкомментарии, я выбрал Ninject вместо StructureMap.

Я не знаю, лучше ли Ninjectчем StructureMap, но, с моей точки зрения, определенно гораздо проще начать и начать работу.

1 Ответ

10 голосов
/ 11 ноября 2010

ОК,

Я уверен, Джереми Миллер исправит мой пост и даст вам настоящую правду, но идея иметь тот пользовательский Controller factory, который использует StructureMap дляСоздайте контроллеры, потому что Controller class является классом ключей , где большая часть логики запускается и происходит (да, есть фильтры действий и тому подобное, что происходит раньше, но давайте будем проще) - и для этого необходимо предварительно настроить все зависимости, прежде чем начнется любая логика.

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

Это ядро ​​DI / IoC.

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


Предположим, у нас есть следующий метод в контроллере: -

public ActionMethod Index()
{
   // List all Products.
}

Довольно просто.Просто перечисляет некоторые продукты в браузере.Итак, первое, что вам нужно спросить, это -> что такое Products?откуда они?Ну, метод контроллера не задает этот вопрос вообще.На самом деле, это НЕ КАСАЕТСЯ откуда они пришли.Его заботит только то, что он имеет что-то , то есть Product.

Так что, когда мы используем этот метод, нам также не нужно заботиться о том, где находится информация о продукте.Мы просто хотим сделать что-то с этими вещами, которые называются Products '.

Хорошо ... так что давайте сделаем что-то с этим ...

public ActionMethod Index()
{
   var products = _myProductService.Find().ToList();

   // .. rest snipped.
}

Хорошо ... пока мы сейчаспопросить некоторые службы найти все продукты и затем перечислить их.Kewl.Тем не менее, нам все равно, откуда эти продукты.Или даже, что это Product Service.Это ключ -> Мы оставляем DI / IoC беспокоиться об этом .Все, что нас волнует, это тот факт, что у нас есть ProductService, который делает некоторые вещи с некоторыми продуктами.В этом случае он собирается Find всех продуктов, а затем мы просим его перечислить все найденные продукты.

Так, где DI / IoC вступает в игру?

ЭтоВолшебная часть единорога:)

Когда этот контроллер был инстанцирован , он спросил StructureMap:

"Oi! StructureMap! Мне нужно создать HomeController.Но у HomeController есть по крайней мере один конструктор ... и самый сложный конструктор, который у него есть (примечание: DI / IoC называет это самым жадным конструктором ), перечисляет ряд объектов, которые ему требуются. Итак ... Iнужно сначала создать эти объекты, затем создать мой HomeController .. и передать эти объекты в. передать эти объекты в.

Давайте посмотрим на код ...

public class HomeController : Controller
{
    private IProductService _productService;
    private ILoggingService _loggingService;

    public HomeController(IProductService productService, ILoggingService loggingService)
    {
       _productService = productService;
       _loggingService = loggingService;
    }

    public ActionMethod Index()
    {
        var products = _productService.Find().ToList();

        // rest snipped.
    }
}

Вау - здесь происходит несколько вещей. Давайте вспомним -> Итак, StructureMap говорит:

Мне нужен экземпляр IProductService и ILoggingService .., которые я передаю HomeControllerконструктор ... ты можешь дать мне это, пожалуйста? "

И StructureMap тогда говорит:

Хорошо .. сначала -> IProductService.Давайте посмотрим здесь, вы сопоставили IProductService с вашим пользовательским классом, названным ReallyFastProductService.Кьюл, я создам одного из тех плохих парней.Далее, вы сопоставили ILoggingService с классом NLogLoggingService ... приятно!NLog Wroxs, чувак.Так что я тоже создам одного из тех плохих парней.Хорошо, теперь я сделал эти два экземпляра.В заключение!Теперь я могу создать экземпляр HomeController, который вам нужен ... и затем я передам эти два объекта, которые я только что создал, в конструктор HomeController ... и альт!вот экземпляр Controller.

... так что теперь у вас есть экземпляр Controller.

.... и когда вы входите в метод Index (), если вы используетемышь и наведите курсор мыши на экземпляры, они будут ReallyFastProductService и NLogLoggingService.

Отлично!Таким образом, это означает, что метод Index() никогда не тесно связан с конкретной реализацией класса.

Теперь вы решили, что вам не нравится весь код, который вы делали вReallyFastProductService и решил написать еще один, который использует некоторые новые уловки и навыки, которые вы только что приобрели.Итак, теперь вы делаете второй класс с именем PewPewProductService, потому что он pwns.Теперь, если вы измените отображение StructureMap с ...

ObjectFactory.Configure(x => 
    { x.For<IProductService>().Add(new ReallyFastProductService());});

на

ObjectFactory.Configure(x => 
    { x.For<IProductService>().Add(new PewPewProductService());});

... внезапно, все методы в этом HomeController теперь ссылаются на логику в новомкласс вы только что построили.Нет необходимости изменять какой-либо код в контроллере.

Поймайте пенни, когда она упадет:)

Добро пожаловать в DI / IoC и почему он пинает серьезный приклад.*

...