小引

在 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. linux 网卡配置文件详解

    配置文件位置:/etc/sysconfig/network-scripts/ifcfg-eth0 1. DEVICE=eth0 网卡的名字 2. HWADDR=00:0c:29:90:89:d9 HW ...

  2. java 读取项目外面配置文件的方法

    public static void loadProps(String propertiesUrl) { props = new Properties(); InputStream in = null ...

  3. 浅谈Linux下各种压缩 解压命令和压缩比率对比

    Linux下压缩.解压命令五花八门,不像在windows下一个winrar打遍天下无敌手,清一色的.rar .zip格式. 比如,Linux下常用的tar tar.gz tar.bz2 .Z等等不一而 ...

  4. spring集成Quartz时区问题造成任务晚执行八小时

    项目中在Spring中集成了Quartz,配置的每日凌晨执行的定时任务都是到了八点多才执行,经过一番查找,可能是时区问题造成的. 一种解决办法是在JVM启动参数中增加 --Duser.timezone ...

  5. numpy 辨异(四)—— np.repeat 与 np.tile

    >> import numpy as np >> help(np.repeat) >> help(np.tile) 二者执行的是均是复制操作: np.repeat: ...

  6. Extension of write anywhere file system layout

    A file system layout apportions an underlying physical volume into one or more virtual volumes (vvol ...

  7. Java反射获取内部类有局限

    这周接触到继承及修改具有包访问权的内部类内容,略梳理了下各种资料,发觉在包外修改内部类内容必须通过实例....... 网上关于这部分的内容比较少,参考了下这位的帖子:http://blog.csdn. ...

  8. Linux下快速静态编译Qt以及Qt动态/静态版本共存(提供了编译4.6,5.6的精通编译脚本,并且apt-get install 需要的库也全列出来了。还有分析问题的心理过程)good

    qt4.6 Linux./configure -static -release -confirm-license -opensource -qt-zlib -qt-libpng -qt-libjpeg ...

  9. mac在下面Apache 创 .htaccess档

    在设定一个固定的链接将提下面的例子说明样题: 若您的 .htaccess 文件可写.我们能够自己主动改动它.但似乎它不可写,因此我们在下方列出了您 .htaccess 文件里应该增加的URL 重写规则 ...

  10. HTML5逐步实现

    渐变 Context对象能够通过createLinearGradient()和createRadialGradient()两个方法创建渐变对象.这两个方法的原型例如以下: Object createL ...