Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Также у нас есть интерфейс 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-архитектурой, которую схематически можно выразить следующим образом: