MVC專案實踐,在三層架構下實現SportsStore-03,Ninject控制器工廠等

Darren Ji發表於2014-06-27

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 }
            );

執行,得到如下介面:

5

 

在資料庫中也新增了MySportsStore資料庫:

6

原始碼在這裡

 

“MVC專案實踐,在三層架構下實現SportsStore”系列包括:

MVC專案實踐,在三層架構下實現SportsStore,從類圖看三層架構

MVC專案實踐,在三層架構下實現SportsStore-01,EF Code First建模、DAL層等

MVC專案實踐,在三層架構下實現SportsStore-02,DbSession層、BLL層

MVC專案實踐,在三層架構下實現SportsStore-03,Ninject控制器工廠等

MVC專案實踐,在三層架構下實現SportsStore-04,實現分頁

MVC專案實踐,在三層架構下實現SportsStore-05,實現導航

MVC專案實踐,在三層架構下實現SportsStore-06,實現購物車

MVC專案實踐,在三層架構下實現SportsStore-07,實現訂單提交

MVC專案實踐,在三層架構下實現SportsStore-08,部署到IIS伺服器

MVC專案實踐,在三層架構下實現SportsStore-09,ASP.NET MVC呼叫ASP.NET Web API的查詢服務

MVC專案實踐,在三層架構下實現SportsStore-10,連線字串的加密和解密

MVC專案實踐,在三層架構下實現SportsStore-11,使用Knockout實現增刪改查

相關文章