小引

在 ASP.NET 5(vNext)之前,亦即 MVC 4/5、Web API 2 的时代,MVC 与 Web API 框架彼此有非常相似的设计,却是以不同的代码来实现。现在,ASP.NET 5 集成了 MVC、Web API、与 Web Pages 程序模型于单一框架,统称为 MVC 6。

ASP.NET 5 的另一个亮点是自帶 Dependency Injection 容器。在此之前的 MVC 与 Web API 框架对于 DI 的支持则相对薄弱,主角是 IDependencyResolver 接口。

ASP.NET 5 的自帶 DI 容器可能已经能够满足大部分的 DI 基础操作,这表示将来我们对其他 DI 框架(如 Unity、Autofac)的依赖程度可能会逐渐降低。

这里就要来牛刀小试一下 ASP.NET 5 自帶的 DI 容器。

需要的工具:Visual Studio 2015 Preview

注意:由于 ASP.NET 5 仍在 beta 测试阶段,Visual Studio 2015 也是预览版,所以本文的操作画面截图和程序范例可能会跟将来的正式版有些出入。

练习步骤

步骤 1 :建立项目

开启 Visual Studio 2015,建立一个新的 ASP.NET Web Application 项目,参考下图:

项目名称命名为 DependencyInjectionDemo。按 OK 之后,接着选择模板「ASP.NET 5 Empty」:

项目建立完成后,大概看一下 Solution Explorer 里面有哪些东西:

根目录下的 project.json 即是此项目的配置文件,其中包含此项目所依赖的框架与组件。Startup.cs 则会包含应用程序激活时所需执行的初始化工作。

步骤 2 :加入必要组件

项目刚建立完成时的 project.json 内容如下:

{
"webroot": "wwwroot",
"version": "1.0.0-*",
"exclude": [
"wwwroot"
],
"packExclude": [
"**.kproj",
"**.user",
"**.vspscc"
],
"dependencies": {
"Microsoft.AspNet.Server.IIS": "1.0.0-beta1",
},
"frameworks" : {
"aspnet50" : { },
"aspnetcore50" : { }
}
}

我们得在「dependencies」区段中加入 ASP.NET MVC 组件:"Microsoft.AspNet.Mvc": "6.0.0-beta1"(你的开发环境可能是别的版本号)。这些文字都要自己敲进去,不过还好,Visual Studio 有智能提示功能,如下图:

註:若没出现智能提示,可按【Alt+右箭头键】令它显现。

输入冒号之后,会接着提示版本,如下图:

虽然移到最底下就能选择最新的 beta 版本,但它可不一定能在你目前的开发环境上顺利运行。保险起见,还是选最上方的 「6.0.0-beta1」。

修改完毕之后,「dependencies」区块的内容会像这样:

"dependencies": {
"Microsoft.AspNet.Server.IIS": "1.0.0-beta1",
"Microsoft.AspNet.Mvc": "6.0.0-beta1"
},

说明:

  • Microsoft.AspNet.Server.IIS -由于我们要使用 IIS 来做为此应用程序的装载平台,所以必须加入此套件。
  • Microsoft.AspNet.Mvc -这是 MVC 与 Web API 的核心套件。

步骤 3 :将 Web API 组件加入 ASP.NET 管线

开启 Startup.cs,参考以下范例来修改代码:

using System;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.Framework.DependencyInjection; // 别忘了这个!
using Microsoft.AspNet.Hosting; // 别忘了这个! namespace DependencyInjectionDemo
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
} public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
}
}

说明:

  • Configure 方法有一个传入参数 app,类型是 IApplicationBuilder。这里使用它的 UseMvc 方法来将 MVC/Web API 组件加入至应用程序的管线作业流程。ASP.NET 框架会在应用程序激活时主动呼叫此方法。
  • ConfigureServices 方法也会由 ASP.NET 框架主动呼叫,我们可以在这里设定应用程序所需之服务(包括向 DI 容器注册类型)。注意此方法的传入参数 services,类型是 IServiceCollection;它就是 ASP.NET 5 自帶的 DI 容器。我们可以透过这个容器来注册相依对象的类型对应关系,这个部分稍后会有范例程序。

註:IServiceCollection 接口隶属于命名空间 Microsoft.Framework.DependencyInjection。

步骤 4 :加入 API Controller

在 Solution Explorer 中,项目的根目录下建立一个文件夹:Controllers。然后在此文件夹上点右键,选 Add > New Item。在新开启的对话窗中选择「Web API Controller Class」,并将档案命名为 ValuesController.cs。参考下图:

产生的代码大致如下:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Mvc; namespace DependencyInjectionDemo.Controllers.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET: api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
} // 省略其余 Get/Post/Put/Delete 方法。
}
}

OK! 现在按 F5 或 Ctrl+F5,看看应用程序能否正常运作。请注意,浏览器的地址栏必须手动修改成这样:

http://[主机名: 端口号]/api/Values

若没出现错误讯息,便可继续下一个步骤。

步骤 5 :撰写测试用的服务类别

写一个简单的类别来作为注入至 controller 的对象。如下所示:

namespace DependencyInjectionDemo
{
public interface ITimeService
{
string Now { get; }
} public class TimeService : ITimeService
{
public string Now
{
get
{
return DateTime.Now.ToString();
}
}
}
}

代码很简单,就不多解释了。

步骤 6 :注入相依对象至 Controller 的构造函数

修改 ValuesController 类别,让它看起来像这样:

public class ValuesController : Controller
{
private readonly ITimeService _timeService; public ValuesController(ITimeService timeService)
{
_timeService = timeService;
} // GET: api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { _timeService.Now };
} // 省略其余 Get/Post/Put/Delete 方法。
}

这表示我们希望 ASP.NET 框架在建立此 controller 对象时, 能够一并注入它需要的 ITimeService 对象。用 DI 术语来说,这里使用了「建构式注入」(Constructor Injection)来避免我们的 API Controller 跟特定实现类别绑太紧——ValuesController 依赖的是抽象的 ITimeService 接口,而非具象类别 TimeService。

再执行一次应用程序看看,由于 MVC 框架找不到 ValuesController 的默认构造函数,浏览器应该会显示错误讯息,如下图:

解决方法很简单,只要在你的 Startup 类别的 ConfigureServices 方法中注册 ITimeService 类型所对应的实现类别就行了。

    public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
} public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddScoped<ITimeService, TimeService>(); // 加这行!
}
}

这里是透过 IServiceLocation 的扩展方法 AddScope 来向 ASP.NET 自帶的容器注册类型对应关系,意思是:碰到需要 ITimeService 对象的时候,使用 TimeService 来建立对象实体。

此外,从方法的名称大约可以猜得出来,这个 AddScope 方法还有另一个意义,那就是:将来容器在建立 ITimeService 对象时(用 DI 术语来说,就是「解析 ITimeService」),会建立一个「活在特定范围内」的对象。就此范例而言,这个特定范围就是一个 HTTP 请求的范围。

如此一来, 当 MVC 框架在建立 ValuesController 时, 发现它的构造函数需要一个 ITimeService 对象,于是 MVC 框架就会跟自帶容器要一个 ITimeService 对象,然后将此对象传入 ValuesController 的构造函数。

再执行一次应用程序,这次应该能够顺利执行了。执行结果如下图:

很简单吧?这里完全没用到第三方 DI 框架。

运用相同技巧,你可以将任何对象注入至你的 Controller 类别,例如应用层(application layer)的各类服务/组件。

结语

ASP.NET 5 的自帶 DI 容器支持四种生命周期模式:Instance、Singleton、Transient、Scoped。本文范例中使用的 AddScoped 方法即为 Scoped,或者说 Per Request 生命周期模式,亦即对象只存活在目前请求的范围内,且同一请求范围内会共享同一个对象实体。

如欲进一步了解 ASP.NET 5 的 DI 功能与限制,可参考下列文章:

ASP.NET 5 (vNext) 牛刀小試:自帶 DI 容器的更多相关文章

  1. ASP.NET 5 牛刀小試(二):加入第三方 DI 容器

    上回介绍了 ASP.NET vNext 自带容器的基本用法,这次要试试把 ASP.NET vNext 的自带容器换成 Autofac. 这一次,在编写范例程序的过程中,光是解决 KRE 与相关套件的版 ...

  2. Linux部署ASP.NET 5 (vNext)

    原文:Linux部署ASP.NET 5 (vNext) ASP.NET 5 (vNext) Linux部署   引言 工欲善其事,必先利其器. 首先,我们先明确下以下基本概念 Linux相关 Ubun ...

  3. ASP.NET 5 (vNext)

    ASP.NET 5 (vNext) 理解和入门   概述 ASP.NET 5 (又称为vNext) 是自ASP.NET产生15年以来一次革命性的更新, 我们可以从以下几点来理解其概貌和意义: ASP. ...

  4. net core体系-web应用程序-4net core2.0大白话带你入门-8asp.net core 内置DI容器(DependencyInjection,控制翻转)的一点小理解

    asp.net core 内置DI容器的一点小理解   DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IO ...

  5. 面试题之小炼牛刀zip,lambda,map

    # 现有两元祖,(('a'),('b')),(('c'),('d'))# 请使用python中匿名函数生成列表[{'a':'c'},{'b':'d'}]t1=(('a'),('b'))t2=(('c' ...

  6. matlab初试牛刀__小练习

    % T1 % 最好还是设 h=2 D=1 clear,clc; h=2;D=1; x=-2*D:0.01:2*D; y=h*(x>D)+h/D.*x.*(abs(x)<=D)-h*(x&l ...

  7. ASP.NET 5 (vNext) Linux部署

    引言 工欲善其事,必先利其器. 首先,我们先明确下以下基本概念 Linux相关 Ubuntu Ubuntu是基于linux的免费开源桌面PC操作系统 十分契合英特尔的超极本定位 支持x86.64位和p ...

  8. ASP.NET 5 (vNext) 理解和概述

    概述 ASP.NET 5 (又称为vNext) 是自ASP.NET产生15年以来一次革命性的更新, 我们可以从以下几点来理解其概貌和意义: ASP.NET 5是开源的 ASP.NET 5开发的WebA ...

  9. Asp.Net Core SignalR 与微信小程序交互笔记

    什么是Asp.Net Core SignalR Asp.Net Core SignalR 是微软开发的一套基于Asp.Net Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给 ...

随机推荐

  1. METHODS OF AND APPARATUS FOR USING TEXTURES IN GRAPHICS PROCESSING SYSTEMS

    BACKGROUND The technology described herein relates to methods of and apparatus for using and handlin ...

  2. Apacheserver自己定义404页面的两种方法以及.htaccess的重要命令总结

    Apacheserver自己定义404错误页面有两种方法: 第一种方法最简单,直接在Apache的httpd.conf下进行配置改动命令,改动的内容请參看.htaccess命令写法中的自己定义错误页面 ...

  3. 【14.36%】【codeforces 614C】Peter and Snow Blower

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  4. selenium 爬取空间说说

    package cn.hb.util; import java.io.File; import java.io.FileWriter; import java.io.IOException; impo ...

  5. hadoop编程技巧(8)---Unit Testing (单元测试)

    所需的环境: Hadoop相关jar包裹(下载版本的官方网站上可以): 下载junit包裹(新以及). 下载mockito包裹: 下载mrunit包裹: 下载powermock-mockito包裹: ...

  6. spring-boot-sample-web-jsp

    Pom文件需要配置的: <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl&l ...

  7. Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作

    本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78615800 Qt实用技巧:使用QTableView.QSqlTableMode与Q ...

  8. 解决mysql连接异常—-com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception

    DBCP连接池连接MySql数据库时,一奇葩数据库设置为30秒内无请求自动断开.超时后链接无法关闭,活动链接数飞奔,最后挂掉. 网上找了一圈,一般是这三种,方法一pass,方法二测试无效可能设置错了吧 ...

  9. REST = HTTP动词(GET POST PUT DELETE)操作 + 服务器暴露资源URI,最后返回状态码(充分利用HTTP自身的特征,而不仅仅是把HTTP当作传输协议。Rest协议是面向资源的,SOAP是面向服务的),表现形式可以是JSON XML BIN,举例很清楚

    好处是,操作系统或者浏览器,可以重复利用它们内置的缓存机制等等. 增删改查都是一个地址,具体靠http头部信息判断. 利用HTTP协议语义构建的语义化.可缓存的接口. URL定位资源,用HTTP动词( ...

  10. Swift程式语言(中国版)(8.8 %)

    前言 今天Apple宣布了一项新的编程语言Swift.还提供了一个近400页The Swift Programming Language(Swift程式语言). 虽然我没有开发者账户.不能实际锻炼机S ...