Home  >  Article  >  Backend Development  >  [ASP.NET MVC Mavericks Road] 05 - Using Ninject

[ASP.NET MVC Mavericks Road] 05 - Using Ninject

黄舟
黄舟Original
2016-12-30 14:08:481761browse

[ASP.NET
MVC Mavericks Road]05 - Using Ninject

The previous article in the [ASP.NET MVC Mavericks Road] series (Dependency Injection (DI) and Ninject ) mentioned two things to do when using Ninject in ASP.NET
MVC. Following this article, this article will use a practical example to demonstrate the application of Ninject in ASP.NET MVC.

In order to better understand and grasp the content of this article, it is strongly recommended that beginners read Dependency Injection (DI) and Ninject before reading this article.

Directory of this article:


Preparation work

Create a new blank solution named BookShop. Add an empty MVC application named BookShop.WebUI and a class library project named BookShop.Domain to the solution. The directory structure is as follows:

[ASP.NET MVC Mavericks Road] 05 - Using Ninject

#After the two projects are added, add a reference to the BookShop.Domain project under the BookShop.WebUI project.

Use NuGet to install the Ninject package for the BookShop.WebUI project and BookShop.Domain project respectively (for an introduction to NuGet, please read Dependency Injection (DI) and Ninject). You can install it through the visual window, or you can open the Package
Manager Console (View->Other Windows->Package Manager Console) and execute the following command to install:

Install-Package Ninject -Project BookShop.WebUI

Install-Package Ninject -Project BookShop.Domain

The following picture shows that the installation is successful:

[ASP.NET MVC Mavericks Road] 05 - Using Ninject

Create Controller Factory

We know that in ASP.NET MVC, a client request is processed in the Action of a specific Controller. By default, ASP.NET MVC uses the built-in Controller factory class DefaultControllerFactory to create a Controller instance corresponding to a certain request. Sometimes the default Controller factory cannot meet our actual needs, so we need to extend this default behavior, that is, create a custom Controller factory class that inherits from the DefaultControllerFactory class and override some of its methods. To this end, we create a folder named Infrastructure under the BookShop.WebUI project, and add a factory class named NinjectControllerFactory in the folder. The code is as follows:

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 in the above code (controllerType) can obtain a Controller instance. Manually instantiating the Controller class here is a very complicated process. We don't know whether the Controller class has a constructor with parameters, nor do we know what types the parameters of the constructor are. To use Ninject, you only need to use the Get method above. Ninject will automatically handle all dependencies internally and intelligently create the objects we need.

After the Controller factory class is created, we need to tell MVC to use our NinjectControllerFactory class to create a Controller object. To do this, add the following code to the Application_Start method of the Global.asax file:

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

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

Here we don’t care about the principle of the above code for the time being. Just know that to set up a custom Controller factory, you must register here. If I have time, I will explain this part in a more in-depth blog post.


Add Domain Model

In an MVC application, everything revolves around the Domain Model (domain model) of. So we created a folder named Entities in the BookShop.Domain project to store the domain entity model. As an e-commerce online bookstore, of course the most important domain entity is Book. Since it is just for demonstration, we simply define a Book class and add this class in the Entities folder. The code is as follows:

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 Mavericks Road] 05 - Using 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 Mavericks Road] 05 - Using Ninject

Conclusion:

This article is a simple example of using Ninject in ASP.NET MVC. The purpose is to let everyone understand how to use Ninject in MVC. Of course, the power of Ninject is not limited to what is demonstrated in this article. I believe that after you become familiar with Niject, you will definitely like it when building MVC applications.

The above is the content of [ASP.NET MVC Mavericks Road] 05 - Using Ninject. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn