首頁  >  文章  >  後端開發  >  [ASP.NET MVC 小牛之路]05 - 使用 Ninject

[ASP.NET MVC 小牛之路]05 - 使用 Ninject

黄舟
黄舟原創
2016-12-30 14:08:481823瀏覽

[ASP.NET
MVC 小牛之路]05 - 使用Ninject

在[ASP.NET MVC 小牛之路]系列上一篇文章(依賴注入(DI)和Ninject)的末尾提到了在ASP. NET
MVC中使用Ninject要做的兩件事情,續這篇文章之後,本文將以一個實際的範例來示範Ninject在ASP.NET MVC中的應用。

為了更好的理解和撐握本文內容,強烈建議初學者閱讀本文前先閱讀依賴注入(DI)和Ninject。

本文目錄:


準備工作

新建一個名為BookShop的空白解決方案。在該解決方案中分別新增一個名為BookShop.WebUI的MVC空白應用程序,和一個名為BookShop.Domain的類別庫工程。目錄架構如下:

[ASP.NET MVC 小牛之路]05 - 使用 Ninject

兩個工程加入完後,在BookShop.WebUI工程下加入BookShop.Domain工程的引用。

使用NuGet分別為BookShop.WebUI工程和BookShop.Domain工程安裝Ninject套件(NuGet的介紹請閱讀依賴注入(DI)和Ninject)。可以透過視覺化視窗安裝,也可以開啟Package
Manager Console(視圖->其他視窗->Package Manager Console)執行下列指令安裝:

Install-Package Ninject -Project BookShop.WebUI 
.Domain

下圖說明安裝成功:

[ASP.NET MVC 小牛之路]05 - 使用 Ninject

建立Controller Factory

我們知道,在ASP.NET MVC中,一個客戶端請求是在特定Controller的Action中進行處理的。 預設情況下,ASP.NET MVC使用內建的Controller工廠類別 DefaultControllerFactory來建立某個請求對應的Controller實例。有時候預設的Controller工廠無法滿足我們實際的需求,我們就需要對這種預設行為進行擴展,即創建一個繼承自DefaultControllerFactory類別的自訂Controller工廠類別並重寫其中的一些方法。為此,我們在BookShop.WebUI工程下建立一個名為Infrastructure的資料夾,在該資料夾中新增一個名為NinjectControllerFactory的工廠類,程式碼如下:

public class NinjectControllerFactory : DefaultControllerFactory {
    private IKernel ninjectKernel;

    public NinjectControllerFactory() {
        ninjectKernel = new StandardKernel();
        AddBindings();
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
        return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
    }

    private void AddBindings() {
        // todo:后面再来添加绑定
    }
}

上面程式碼中的ninjectKernel.Get(controllerType) 可取得到一個Controller實例。這裡如果手動實例化Controller類別是一個非常複雜的過程,我們不知道Controller類別有沒有參數的建構函數,也不知道建構函數的參數是什麼型別。而使用Ninject只需要使用上面的一個Get方法就可以,Ninject內部會自動處理所有的依賴關係,聰明地建立我們需要的物件。


Controller工廠類別創建好後,我們就需要告訴MVC用我們的NinjectControllerFactory類別來創建Controller對象,為此,需在Global.asax文件的Application_Start方法中添加下面代碼:

protected void Application_Start() {
    ......

    //设置Controller工厂
    ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}

這裡我們暫且不關心上面這段程式碼是什麼原理,知道設定自訂的Controller工廠必須要在這註冊就行了,有空的話我會在後續博文對這部分內容進行更深入的講解。


添加Domain Model

在MVC應用程式中,一切都是圍繞Domain Model(領域模型)來的。 所以我們在BookShop.Domain工程中專門建造一個名為Entities的資料夾,用來存放領域實體模型。作為一個電子商務類的網路書店,當然最重要的一個領域實體就是Book了。由於只是為了演示,我們簡單定義一個Book類,並在Entities資料夾中添加該類,程式碼如下:

public class Book {
    public int ID { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
    public string Summary { get; set; }
    public string Author { get; set; }
    public byte[] Thumbnail { get; set; }
    public decimal Price { get; set; }
    public DateTime Published { get; set; }
}

添加Repository

我们知道,我们肯定需要一种方式来从数据库中读取Book数据。在这我们不防为数据的使用者(这里指Controller)提供一个IBookRepository接口,在这个接口中声明一个IQueryable类型的属性Books。这样,通过该接口使用依赖注入,使用者就可以拿到Books数据集合,而不用关心数据是如何得到的。为此,我们在BookShop.Domain工程中添加一个名为 Abstract的文件夹,在该文件夹中添加我们的IBookRepository接口文件,代码如下:

public interface IBookRepository {
    IQueryable<Book> Books { get; }
}

在MVC中我们一般会用仓储模式(Repository Pattern)把数据相关的逻辑和领域实体模型分离,这样对于使用者来说,通过调用仓储对象,使用者可以直接拿到自己想要的数据,而完全不必关心数据具体是如何来的。我们可以把仓储比喻成一个超市,超市已经为消费者供备好了商品,消费者只管去超市选购自己需要的商品,而完全不必关心这些商品是从哪些供应商怎么样运输到超市的。但对于仓储本身,必须要实现读取数据的“渠道”。

在BookShop.Domain工程中添加一个名为Concrete文件夹用于存放具体的类。我们在Concrete文件夹中添加一个实现了IBookRepository接口的BookRepository类来作为我们的Book数据仓储。BookRepository类代码如下:

public class BookRepository : IBookRepository {

    public IQueryable<Book> Books {
        get { return GetBooks().AsQueryable(); }
    }

    private static List<Book> GetBooks() {  
        //为了演示,这里手工造一些数据,后面会介绍使用EF从数据库中读取。
        List<Book> books = new List<Book>{
            new Book { ID = 1, Title = "ASP.NET MVC 4 编程", Price = 52},
            new Book { ID = 2, Title = "CLR Via C#", Price = 46},
            new Book { ID = 3, Title = "平凡的世界", Price = 37}
        };
        return books;
    }
}

为了演示,上面是手工造的一些数据,后面的文章我将介绍使用Entity Framwork从数据库中读取数据。对于刚接触ORM框架的朋友可能对这里IQueryable感到奇怪,为什么用IQueryable作为返回类型,而不用IEnumerable呢?后面有机会讲Entity Framwork的时候再讲。

添加绑定

打开之前我们在BookShop.WebUI工程创建的NinjectControllerFactory类,在AddBindings方法中添加如下代码

private void AddBindings() {
    ninjectKernel.Bind<IBookRepository>().To<BookRepository>();
}

这句代码,通过Ninject把IBookRepository接口绑定到BookRepository,当IBookRepository接口的实现被请求时,Ninject将自动创建BookRepository类的实例。

到这里,Ninject的使用步骤就结束了,接下来我们把本示例剩余的步骤完成。


显示列表

右击BookShop.WebUI工程的Controllers文件夹,添加一个名为Book的Controller,按下面代码对其进行编辑:

public class BookController : Controller {
    private IBookRepository repository;

    public BookController(IBookRepository bookRepository) {
        repository = bookRepository;
    }
}

在这,BookController的构造函数接受了一个IBookRepository参数,当BookController被实例化的时候,Ninject就为其注入了BookRepository的依赖。接下来我们为这个Controller添加一个名为List的Action,用来呈现Book列表。代码如下:

public class BookController : Controller {
    ...

    public ViewResult List() {
        return View(repository.Books);
    }
}

当然我们需要添加一个View。右击上面的List方法,选择添加视图,在弹出的窗口进行如下配置:

[ASP.NET MVC 小牛之路]05 - 使用 Ninject

然后我们在List.cshtml中用foreach循环来列举书本信息,代码如下:

@model IEnumerable<BookShop.Domain.Entities.Book>

@{
    ViewBag.Title = "Books";
}

@foreach (var p in Model) {  
    <div class="item" style="border-bottom:1px dashed silver;"> 
        <h3>@p.Title</h3> 
        <p>价格:@p.Price.ToString("c") </p>   
    </div>     
}

最后我们还需要修改一下默认路由,让系统运行后直接导向到我们的{controller = "Book", action = "List"},打开Global.asax文件,找到RegisterRoutes方法,进行如下修改:

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name 
        "{controller}/{action}/{id}", // URL with parameters 
        new { controller = "Book", action = "List", id = UrlParameter.Optional }
    );
}

到这,我们的程序可以运行了,效果如下:

[ASP.NET MVC 小牛之路]05 - 使用 Ninject

結論:

本文是Ninject在ASP.NET MVC中使用的簡單範例,目的是讓大家了解Ninject在MVC中的使用方法。當然,Ninject的強大之處不僅限於本文所示範的,相信當你熟悉了Niject之後,在搭建MVC應用程式時,你一定會喜歡上它的。

 以上就是[ASP.NET MVC 小牛之路]05 - 使用 Ninject的內容,更多相關內容請關注PHP中文網(www.php.cn)!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn