Onion-архитектура. Часть 2

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 21.03.2018

Также у нас есть интерфейс IOrder. И для его реализации определим в папке Infrastructure дополнительный проект по типу Class Library, который назовем OnionApp.Infrastructure.Business. Добавим к нему ссылки на проекты OnionApp.Domain.Core и OnionApp.Services.Interfaces.

Здесь мы можем определить разные реализации интерфейса IOrder. Например:

using OnionApp.Domain.Core;
using OnionApp.Services.Interfaces;

namespace OnionApp.Infrastructure.Business
{
    public class CacheOrder : IOrder
    {
        public void MakeOrder(Book book)
        {
            // код покупки книги при оплате наличностью
        }
    }
}

Для простоты примера я опустил код. Подобным образом можно создать и другие возможные реализации:

using OnionApp.Domain.Core;
using OnionApp.Services.Interfaces;

namespace OnionApp.Infrastructure.Business
{
    public class CreditOrder : IOrder
    {
        public void MakeOrder(Book book)
        {
            // код покупки книги с помощью кредитной карты
        }
    }
}

Теперь, когда все необходимые проекты готовы, мы можем перейти к созданию веб-интерфейса для управления функционалом. Для этого будем использовать имеющийся по умолчанию проект OnionApp. В этом проекте уже есть стандартный HomeController. Изменим его таким образом, чтобы он использовал зависимости из ранее созданных проектов:

using System.Web;
using System.Web.Mvc;
using OnionApp.Domain.Core;
using OnionApp.Domain.Interfaces;
using OnionApp.Services.Interfaces;

namespace OnionApp.Controllers
{
    public class HomeController : Controller
    {
        IBookRepository repo;
        IOrder order;
        public HomeController(IBookRepository r, IOrder o)
        {
            repo = r;
            order = o;
        }
        public ActionResult Index()
        {
            var books = repo.GetBookList();
            return View(books);
        }

        public ActionResult Buy(int id)
        {
            Book book = repo.GetBook(id);
            order.MakeOrder(book);
            return View();
        }
		protected override void Dispose(bool disposing)
        {
            repo.Dispose();
            base.Dispose(disposing);
        }
    }
}

Но чтобы связать зависимости, воспользуемся контейнером зависимостей Ninject. Добавим в проект OnionApp через NuGet пакет Ninject.MVC5 также, как это было показано в статье IoC-контейнер Ninject.

Чтобы зарегистрировать зависимости, создадим в проекте OnionApp каталог Util, в который добавим новый класс NinjectRegistrations:

using Ninject.Modules;
using OnionApp.Domain.Interfaces;
using OnionApp.Infrastructure.Business;
using OnionApp.Infrastructure.Data;
using OnionApp.Services.Interfaces;

namespace OnionApp.Util
{
    public class NinjectRegistrations : NinjectModule
    {
        public override void Load()
        {
            Bind<IBookRepository>().To<BookRepository>();
            Bind<IOrder>().To<CacheOrder>();
        }
    }
}

Данный класс связывает IBookRepository с BookRepository и IOrder с CacheOrder.

Затем перейдем к файлу Global.asax и изменим его следующим образом:

using Ninject;
using Ninject.Modules;
using Ninject.Web.Mvc;
using OnionApp.Util;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace OnionApp
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            // внедрение зависимостей
            NinjectModule registrations = new NinjectRegistrations();
            var kernel = new StandardKernel(registrations);
            DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
        }
    }
}

И, поскольку наше веб-приложение использует Entity Framework, то добавим в проект OnionApp пакет Entity Framework и в файле web.config пропишем строку подключения:

<connectionStrings>
    <add name="OrderContext" providerName="System.Data.SqlClient" 
		connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename='|DataDirectory|\Bookstore.mdf';Integrated Security=True" />
</connectionStrings>

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

В итоге у нас получилось шесть проектов:

Таким образом, мы создали приложение с onion-архитектурой, которую схематически можно выразить следующим образом:

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850