2009-09-26 3 views
11

Я рассмотрел более простые приложения, такие как Nerddinner и ContactManager, а также более сложные, такие как Kigg. Я понимаю более простые, и теперь я хотел бы понять более сложные.Принимая мой MVC на следующий уровень: DI и блок работы

Обычно простые приложения имеют классы и интерфейсы репозитория (как они слабо связаны друг с другом, как они могут быть) поверх LINQtoSQL или Entity Framework. Репозитории вызываются из контроллеров для выполнения необходимых операций с данными.

Один общий шаблон я вижу, когда я рассматриваю более сложные приложения, такие как Kigg или Oxite является введение (я только царапать поверхность здесь, но я должен начать где-то):

  • МОК DI (в Kigg-х дело Unity)
  • Web менеджер Запрос Lifetime
  • Единица работы

Вот мои вопросы:

Я понимаю, что для того, чтобы действительно иметь слабосвязанное приложение, вы должны использовать что-то вроде Unity. Но также кажется, что, как только вы внедряете Unity в микс, вам также нужно представить Web Lifetime Manager. Почему это? Почему в примерах приложений, таких как Nerddinner, нет диспетчера жизненных циклов веб-запросов? Что именно он делает? Это единственная особенность?

Второй образец, который я замечаю, - это введение Единицы работы. Опять же, тот же вопрос: почему Nerddinner или ContactManager не используют Единицу работы? Вместо этого эти приложения используют классы репозитория поверх Linq2Sql или Entity Framework для обработки данных. Никаких признаков какой-либо Единицы работы. Что именно это и зачем его использовать?

Благодаря

Ниже приведен пример DI в Nerddiner на уровне DinnersController:

public DinnersController() 
     : this(new DinnerRepository()) { 
    } 

    public DinnersController(IDinnerRepository repository) { 
     dinnerRepository = repository; 
    } 

Так я прав предположить, что из-за первого конструктора контроллер «владеет» DinnerRepository и будет поэтому зависеть от времени жизни контроллера, так как он объявлен там?

ответ

3

С использованием Linq-to-SQL напрямую ваш контроллер владеет ссылкой на контекст данных , Это обычно частная ссылка внутри контроллера, и поэтому создается как часть ее построения. В управлении жизненным циклом нет необходимости, поскольку он находится в одном месте.

Однако, когда вы используете контейнер IoC, ваш репозиторий данных создается вне вашего контроллера. Поскольку контейнер IoC, который создает его для вас, не знает, как и как долго вы собираетесь использовать созданный объект, вводится стратегия жизни.

Например, контекст данных (репозиторий) обычно создается в начале веб-запроса и уничтожается в конце. Однако для компонентов, которые работают с внешним веб-сервисом, или с каким-то статическим картографом (например, logger), нет необходимости создавать их каждый раз. Поэтому вы можете сказать, чтобы создать их один раз (например, один стиль жизни).

Все это происходит потому, что контейнер IoC (например, Unity) предназначен для обработки многих ситуаций, и они не знают ваших конкретных потребностей. Например, некоторые приложения используют транзакции «беседы», в которых NHibernate (или Entity Framework) может продолжаться в течение нескольких страниц/веб-запросов. Контейнеры IoC позволяют настраивать срок службы объектов в соответствии с вашими потребностями. Но, поскольку это говорит о цене, поскольку нет единой предопределенной стратегии, вы должны выбрать ее самостоятельно.

Почему NerdDinner и другие приложения не используют более сложные методы, просто потому, что они предназначены для демонстрации возможностей MVC, а не для продвинутых способов использования некоторых других библиотек. Я помню статью, написанную для демонстрации одной расширенной функциональности контейнера IoC - эта статья нарушила некоторые утвержденные шаблоны проектирования, такие как разделение проблем, - но это было не так важно, потому что шаблоны проектирования не были целью статьи. То же самое с простыми демонстрационными приложениями MVC - они не хотят, чтобы вы, новичок MVC, терялись в лабиринтах IoC.

И я бы не рекомендовал смотреть на Oxite как дизайн ссылочного примера: http://codebetter.com/blogs/karlseguin/archive/2008/12/15/oxite-oh-dear-lord-why.aspx http://ayende.com/Blog/archive/2008/12/19/oxite-open-exchangable-informative-troubled-engine.aspx

+0

Спасибо! Это помогло. Я редактировал мой вопрос внизу. Это то, что вы имеете в виду, когда говорите, что контроллер владеет ссылкой на контекст репозитория/данных? – Thomas

+0

Не совсем. В NerdDinner они используют дополнительный конструктор, принимающий IDinnerRepository, чтобы упростить модульные тесты. Но да, это все равно либо контроллер (конструктор без параметров), либо тесты, которые создают и владеют объектом репозитория. Они оба умирают, и нет других пользователей репозитория; поэтому жизнь проста. Кстати, такая техника плохая; вы можете узнать больше об этом здесь: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/07/03/how-not-to-do-dependency-injection-in-nerddinner.aspx (также как google для «IoC бедного человека»). – queen3

+0

Аргумент Джимми Богарда об этом, являющемся наглядным примером «IoC бедного человека», здесь очень хорош. Замечания также хороши. Определенно стоит прочитать. –

0

Большинство, если не все контейнеры DI, я считаю, касаются концепции жизни. В зависимости от используемого сценария вы можете захотеть, чтобы контейнер всегда возвращал один и тот же экземпляр зарегистрированного компонента, тогда как для другого компонента вы можете всегда возвращать новый экземпляр. Большинство контейнеров также позволяют указать, что в конкретном контексте вы хотите вернуть тот же экземпляр и т. Д.

Я не знаю, что Unity очень хорошо (до сих пор я использовал Windsor и Autofac), но я подозревают, что администратор жизненного цикла веб-запроса является реализацией стратегий жизненного цикла, когда один и тот же экземпляр предоставляется контейнером в течение всего жизненного цикла одного веб-запроса. Подобные стратегии вы найдете в таких контейнерах, как Windsor.

Наконец, я полагаю, вы имеете в виду Единицу работы. Единица работы - это, по сути, группа действий, которые вы хотите преуспеть или потерпите неудачу в качестве одной транзакции с атомными операциями. Для более формального описания взгляните на Мартина Фаулера definition. Это концепция, которая приобрела большую популярность в контексте Domain Driven Design. Единица работы отслеживает изменения, которые вы применяете в такой транзакции, и когда время подходит, оно совершает эти изменения в одной транзакции ACID. В NHibernate, например., сеанс поддерживает понятие единицы работы, а точнее отслеживание изменений, в то время как в Linq2SQL это контекст ...

Смежные вопросы