Недавно на хабре появилась статья о Unity. В одном из комментов предложили связать ASP.NET MVC и Unity.

А вот есть прикольная задачка уже не для начинающих — связать ASP.NET MVC с Unity. Требований в целом три:

— обеспечить связывание инфраструктуры контроллеров MVC с инъектором
— модульность
— уникальность контейнера в разрезе сессии

Я бы расписал все, но блин, не успеваю вообще ничего, кроме работы. А вам в рамках обучающих методик будет полезно, имхо.

хабраюзер acerv

Я напишу серию постов о применении Unity в паттернах уровня представления.

Сначала о том что такое MVC.

MVC – Model View Controller – паттерн организации PL (presentation layer – уровень представления). Целью этого паттерна, как и многих других, служит отделение модели (логики работы программы) от представления (средств отображения информации). В итоге применение такого паттерна должно приводить к улучшению тестируемости кода.

В современном виде MVC применяется в вебе. Выглядит так: есть модель – группа классов, которые отдают данные или получают команды, есть различные представления этих данных – HTML, сделанные с помощью какого-либо шаблонизатора, JSON, SOAP, XML или еще какой – либо. Для того чтобы передавать данные от модели к представления вводят контроллер.

Все MVC фреймворки проектируются так, чтобы управление приходило сразу на контроллер. Контроллер вызывает методы модели, если нужно формирует данные для передачи представлению (эти данные называют Presentation Entity, но термин неустоявшийся), и выбирает представление для этих данных.

ASP.NET MVC – фреймворк для ASP.NET, реализующий паттерн MVC.
Контроллеры в ASP.NET MVC – классы, унаследованные от класса Controller, содержащие несколько методов - “действий”  (actions). По умолчанию действия отображаются на различные urlы см помощью механизма раутинга (System.Web.Routing).
Каждое действие возвращает ActionResult, который может вызывать генерацию HTML, сериализацию данных в JSON итд. Можно писать свои ActionResult.

Применение Unity в ASP.NET MVC.

Инфраструктура ASP.NET MVC получает имя контроллера из параметров запроса, формируемых механизмом раутинга, потом вызывает класс ControllerFactory, который по имени возвращает экземпляр контроллера.

Сначала создадим новое asp.net mvc приложение. Оно уже включает в себя большой функционал, его трогать не будем.

Чтобы подключить Unity к механизму создания контроллеров надо написать свой класс ControllerFactory.  По умолчанию используется DefaultControllerFactory, нам надо изменить в нем один метод, который создает объект контроллера.

public class UnityControllerFactory: DefaultControllerFactory
{
    IUnityContainer _container;

    public UnityControllerFactory(IUnityContainer container)
    {
        this._container = container;
    }

    protected override IController GetControllerInstance(Type controllerType)
    {
        if (controllerType == null)
        {
            return null;
        }

        return (IController)_container.Resolve(controllerType);
    }
}

Теперь в Global.asax добавим следующий код.

protected void Application_Start()
{
    var container = new UnityContainer();
    RegisterControllerFactory(container);
    //...
}

private static void RegisterControllerFactory(IUnityContainer container)
{
    var factory = new UnityControllerFactory(container);
    ControllerBuilder.Current.SetControllerFactory(factory);
}

Жмем F5 и все работает! В принципе для успешного применения unity в asp.net mvc этого достаточно.

Собственно инъекция зависимостей.

Буду использовать один класс “бизнес-логики” во всех примерах.

public interface ISayHelloService
{
    string SayHello(string name);
}

public class SayHelloSerivce : ISayHelloService
{
    public string SayHello(string name)
    {
        return "Привет, " + name;
    }
}

Надеюсь комментарии не нужны.

Снова дополним global.asax.

protected void Application_Start()
{
    var container = new UnityContainer();
    RegisterTypes(container);
    RegisterControllerFactory(container);
    //...
}

private static void RegisterTypes(IUnityContainer container)
{
    container
        .RegisterType<ISayHelloService, SayHelloService>();
}

Теперь у нас будут подпихиваться зависимости, осталось создать контроллер куда они будут подпихиваться.

public class SayHelloController : Controller
{
    ISayHelloService _service;

    public SayHelloController(ISayHelloService service)
    {
        this._service = service;
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Index()
    {
        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(string name)
    {
	//Преобразование к object нужно чтобы строка 
	//не была принята за имя View
        return View((object)_service.SayHello(name));
    }
}

Создаем View с типом string, и помещаем в MainContent незамысловатый код:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%using (Html.BeginForm()){%>
    Введите имя <%=Html.TextBox("name")%>
    <br />      
    <input type="submit" value="Сказать привет" />
<%} %>

<%if (!string.IsNullOrEmpty(Model)){%>    
    <h3><%=Html.Encode(Model)%></h3>      
<%} %>
</asp:Content>

Теперь жмем F5, переходим о адресу http://localhost:<порт>/SayHello и смотрим как работает.

Теги : MVC, Unity, .NET, ASP.NET, IoC-контейнер