SportsStore是《精通ASP.NET MVC3框架(第三版)》中演示的MVC專案,在該專案中涵蓋了MVC的眾多方面,包括:使用DI容器、URL優化、導航、分頁、購物車、訂單、產品管理、影象上傳......是不錯的MVC實踐專案,但該專案不是放在多層框架下開發的,離真實專案還有一段距離。本系列將嘗試在多層框架下實現SportsStore專案,並用自己的方式實現一些功能。
本篇為系列第三篇,包括:
■ 5、自定義Ninject控制器工廠
■ 6、專案的第一次執行
5、自定義Ninject控制器工廠
在MySportsStore.WebUI下新增如下引用:
● 新增對Ninject的引用
● 新增對MySportsStore.IBLL的引用
● 新增對MySportsStore.BLL的引用
● 新增對MySportsStore.Model的引用
建立NinjectControllerFactory:
using System.Web.Mvc; using MySportsStore.BLL; using MySportsStore.IBLL; using Ninject; namespace MySportsStore.WebUI.Extension { public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, System.Type controllerType) { return controllerType == null ? null : (IController) ninjectKernel.Get(controllerType); } private void AddBindings() { ninjectKernel.Bind<IProductService>().To<ProductService>(); } } }
在全域性中註冊NinjectControllerFactory
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { ...... ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); } }
為什麼需要NinjectControllerFactory?
Ninject這個DI容器可以幫我們很好地管理介面和實現,並且以屬性或建構函式的形式注入到控制器中,從而呼叫介面實現類的方法。並且,Ninject提供了Get()方法,使得使用Ninject也可以建立Controller。
6、專案的第一次執行
建立BaseController,其中賦予手動垃圾回收的機制。
using System; using System.Collections.Generic; using System.Web.Mvc; namespace MySportsStore.WebUI.Controllers { public class BaseController : Controller { protected IList<IDisposable> DisposableObjects { get; private set; } public BaseController() { this.DisposableObjects = new List<IDisposable>(); } protected void AddDisposableObject(object obj) { IDisposable disposable = obj as IDisposable; if (disposable != null) { this.DisposableObjects.Add(disposable); } } protected override void Dispose(bool disposing) { if (disposing) { foreach (IDisposable obj in this.DisposableObjects) { if (null != obj) { obj.Dispose(); } } } base.Dispose(disposing); } } }
當其它的Controller派生於BaseController時,如果用到型別為IXXXService的XXXService,就通過BaseController的AddDisposableObject(object obj)把該XXXService放到BaseController中的DisposableObjects集合屬性中,在使用Dispose()銷燬這些XXXService。
而在BaseService中也提供了手動垃圾回收機制,可以及時回收CurrentRepository。
最後在BaseRepository中也提供了手動垃圾回收機制,可以及時回收EF上下文。
建立ProductController,使之派生於BaseController:
using System.Web.Mvc; using MySportsStore.IBLL; using Ninject; namespace MySportsStore.WebUI.Controllers { public class ProductController : BaseController { [Inject] IProductService ProductService { get; set; } public ProductController() { this.AddDisposableObject(ProductService); } public ViewResult List() { return View(ProductService.LoadEntities(p => true).AsQueryable()); } } }
對應的Prduct/List.cshtml檢視為:
@model IEnumerable<MySportsStore.Model.Product> @{ ViewBag.Title = "List"; Layout = "~/Views/Shared/_Layout.cshtml"; } @foreach (var item in Model) { <div class="item"> <h3>@item.Name</h3> @item.Description <h4>@item.Price.ToString("c")</h4> </div> }
為了能夠讓EF在第一次執行的時候自動建立資料庫並顯示,我們還需要在MySportsStore.WebUI中的Web.config中配置連線字串:
<connectionStrings> ...... <add name="conn" connectionString="Data Source=.;User=some user name;Password=some password;Initial Catalog=MySportsStore;Integrated Security=True" providerName="System.Data.SqlClient"/> </connectionStrings>
修改預設路由為:
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional } );
執行,得到如下介面:
在資料庫中也新增了MySportsStore資料庫:
原始碼在這裡。
“MVC專案實踐,在三層架構下實現SportsStore”系列包括: