在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来演示Ninject在ASP.NET MVC中的应用。

为了更好的理解和撑握本文内容,强烈建议初学者阅读本文前先阅读依赖注入(DI)和Ninject

本文目录:

准备工作

新建一个名为BookShop的空白解决方案。在该解决方案中分别添加一个名为BookShop.WebUI的MVC空应用程序,和一个名为BookShop.Domain的类库工程。目录结构如下:

两个工程添加完后,在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 
Install-Package Ninject -Project BookShop.Domain
下图说明安装成功:

创建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<Book>类型的属性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方法,选择添加视图,在弹出的窗口进行如下配置:

然后我们在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 }
);
}

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

结束语:

本文是Ninject在ASP.NET MVC中使用的一个简单示例,目的是让大家了解Ninject在MVC中的使用方法。当然,Ninject的强大之处不仅限于本文所演示的,相信当你熟悉了Niject之后,在搭建MVC应用程序时,你一定会喜欢上它的。

使用 Ninject的更多相关文章

  1. Ninject学习(一) - Dependency Injection By Hand

    大体上是把官网上的翻译下而已. http://www.ninject.90iogjkdcrorg/wiki.html Dependency Injection By Hand So what's Ni ...

  2. ASP.NET MVC学前篇之Ninject的初步了解

    ASP.NET MVC学前篇之Ninject的初步了解 1.介绍 废话几句,Ninject是一种轻量级的.基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开 ...

  3. [ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject

    本人博客已转移至:http://www.exblr.com/liam  为什么需要依赖注入 在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特征是关注点分离( ...

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

    在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来 ...

  5. 依赖注入(DI)和Ninject,Ninject

    我们所需要的是,在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种“需要”,就称为DI(依赖注入,Dependency Injection),和所谓的IoC(控制反转,I ...

  6. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(六)

    前言 在接下来的篇幅里将对系统的模块功能进行编写.主要以代码实现为主.这一篇我们需要完成系统模块“角色管理”的相关功能.完成后可以对系统框架结构有进一步了解. Abstract层 之前说过,Abstr ...

  7. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(一)

    前言 本系列源自对EF6 CodeFirst的探索,但后来发现在自己项目中构建的时候遇到了一些问题以及一些解决方法,因此想作为一个系列写下来. 本系列并不是教你怎么做架构设计,但可以参照一下里面的方法 ...

  8. Ninject使用介绍

    #region 第二种写法 /// <summary> /// using(IKernel tKernel=new StandardKernel(new PeoKernelServer() ...

  9. 使用Ninject进行DI(依赖注入)

    Ninject是一个快如闪电.超轻量级的基于.Net平台的依赖注入框架.它能够帮助你把应用程序分离成一个个松耦合.高内聚的模块,然后用一种灵活的方式组装起来.通过使用Ninject配套你的软件架构,那 ...

  10. Ninject之旅之十一:Ninject动态工厂(附程序下载)

    摘要 如果我们已经知道了一个类所有的依赖项,在我们只需要依赖项的一个实例的场景中,在类的构造函数中引入一系列的依赖项是容易的.但是有些情况,我们需要在一个类里创建依赖项的多个实例,这时候Ninject ...

随机推荐

  1. IOC AOP 设计模式

    IOC AOP 不是什么技术而是一种设计模式  学习 IOC AOP 其实是在学习一种思想. 1.IOC IOC其实是 将对象的创建和获取提取到外部.由外部IOC容器提供需要的组件. 看下面代码: p ...

  2. .netcore部署到IIS上出现HTTP Error 502.5 - Process Failure问题解决

    首先网上是有很多解决方案,但是对我这个错误完全没用 如果你们没有环境首先得预装环境如下 1.首先在bing.com下搜索asp.net core download, 然后打开搜索到的信息.NET Do ...

  3. 解决"要执行请求的操作,WordPress需要访问您网页服务器的权限"

    比如我们在VPS主机中创建WordPress站点的时候,会有需要在线安装主题.插件等,但是点击下载安装的时候会有"要执行请求的操作,WordPress需要访问您网页服务器的权限. 请输入您的 ...

  4. 【SQL】- 基础知识梳理(八) - 事务与锁

    事务的概念 事务:若干条T-SQL指令组成的一个操作数据库的最小执行单元,这个整体要么全部成功,要么全部失败.(并发控制) 事务的四个属性:原子性.一致性.隔离性.持久性.称为事务的ACID特性. 原 ...

  5. ASP.NET Session原理及处理方法

    session是怎么存储,提取的 1.在服务器端有一个session池,用来存储每个用户提交session中的数据,Session对于每一个客户端(或者说浏览器实例)是“人手一份”,用户首次与Web服 ...

  6. cinder create volume的流程(1)

    前提:代码的跟踪,使用的是ocata版本 零.执行cinder create 命令,创建数据卷,打开debug开关 [root@osnode241001 ~]# cinder --debug crea ...

  7. Mysql初识数据库《三》数据库概述

    1 什么是数据(Data) 描述事物的符号记录称为数据,描述事物的符号既可以是数字,也可以是文字.图片,图像.声音.语言等,数据由多种表现形式,它们都可以经过数字化后存入计算机 在计算机中描述一个事物 ...

  8. Scrapy 增量式爬虫

    Scrapy 增量式爬虫 https://blog.csdn.net/mygodit/article/details/83931009 https://blog.csdn.net/mygodit/ar ...

  9. Django REST framework序列化

    一.简介 Django REST framework是基于Django实现的一个RESTful风格API框架,能够帮助我们快速开发RESTful风格的API. 官网:https://www.djang ...

  10. java开发系统内核:让内核从严重错误中恢复

    更详细的讲解和代码调试演示过程,请参看视频 用java开发C语言编译器 更详细的讲解和代码调试演示过程,请参看视频 如何进入google,算法面试技能全面提升指南 如果你对机器学习感兴趣,请参看一下链 ...