依赖注入 (DI)
在 ASP.NET 之前的版本,一些组件已经支持了依赖注入,如 MVC, WEB API 和 SignalR。但并不是以统一的整体解决方案的方式提供的。在 ASP.NET 5 中提供了一个新的依赖注入抽象层,它以统一的方式应用在整个 Web 栈中。当你需要用到某些服务(services)时,你可以在启动时,在中间件(middleware)中,在过滤器(filters)中,在控制器(controllers)中,在模型绑定时以及任何管道的虚拟部件中访问此服务。 ASP.NET 5 包含了一个用于引导系统的,极简的依赖注入容器。你可以很容易的把它换成任何你想要的容器(如:Autofac, Ninject 等)。服务的范围(scope)包括:单列(singleton),当前请求(request)或过渡(transient)。
示例:为了演示在 ASP.NET MVC 6 中如何使用构造函数注入,首先要创建一个 ASP.NET 5 Starter Web 工程并添加一个简单的服务:
using System;
namespace WebApplication1
{
public class TimeService
{
public TimeService()
{
Ticks = DateTime.Now.Ticks.ToString();
}
public String Ticks { get; set; }
}
}
这个服务记录构造函数被调用的时间。
之后,在Startup类的ConfigureServices方法中,将这个时间服务注册成为一个过渡服务(transient service):
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient<TimeService>();
}
然后, 将 HomeController 修改为使用构造函数注入的形式。并显示 TimeService 对象被创建时的时间。
public class HomeController : Controller
{
public TimeService TimeService { get; set; }
public HomeController(TimeService timeService)
{
TimeService = timeService;
}
public IActionResult About()
{
ViewBag.Message = TimeService.Ticks + " From Controller";
System.Threading.Thread.Sleep(1);
return View();
}
// Code removed for brevity
}
注意,此控制器没有显式的创建 TimeService。它是在控制器被初始化的时候注入进来的。
在 MVC 6 中,你可以使用 [Activate] 特性(attribute)来实现属性注入。你不仅可以在控制器中使用[Activate] 特性,还可以在过滤器和视图组件中使用它。这意味着你可以简化你的控制器,请看下面的代码:
public class HomeController : Controller
{
[Activate]
public TimeService TimeService { get; set; }
// Code removed for brevity
}
MVC 6 也支持在 Razor 视图中使用依赖注入,这是通过 @inject 关键字实现的。在下面的代码中,我将时间服务直接注入到 about 视图中,并且创建了一个 TimeSvc 属性用来访问它:
@using WebApplication23
@inject TimeService TimeSvc
<h3>@ViewBag.Messageh3>
<h3>
@TimeSvc.Ticks From Razor
h3>
当你运行应用时,你可以看到对于控制器和视图会产生不同的时间。