依赖注入一直是asp.net web框架(Web API,SignalR and MVC)中不可或缺的一部分,但是在以前,这个框架都是各自升级,都有各自的依赖注入实现方式,即使Katana项目想通过Owin将这些项目连接起来,你还是要做统一的容器去支持它们,现在事情有所变化了。
 
抽象
asp.net团队决定提供依赖注入功能通过提炼最流行的IOC容器中最核心的功能,然后让不同的组件实现这些接口来实现依赖注入。
 
 
IServiceProvider
 
这个最主要的接口,开发都可以通过这个接口去检索Ioc容器中已经注册过的服务,这个接口只有一个方法而已:GetService(Type), 类似于Aotufact里的Container.Resolve<service>,或者Ninject里的Kernel.Get<service>.
    
所有的MiddleWare有两种方式可以获得所要的IserviceProvider.
  • 应用程序级别:通过HttpContext.ApplicationServices 属性提供给 MiddleWare
  • 请求级别:通过HttpContext.RequestServices属性提供给MiddleWare,这个范围的ServiceProvider通过一个隐式的MIddleWare在最开始的请求管理道中被创建,在请求最后返回响应前被释放。
 
全部的MiddleWare可通过这些属性去解决他们的服务,例如ASP.NET MVC MIddleWare会通过RequestServices去创建Controllers和他们的依赖
 
IServiceScope
 
这个接口是容器的一个包装,主要作用是在请求结束后去释放容器
  • IServiceProvider 
  • Dispose()
 
IServiceScopeFactory
很简单的一个接口,只有一个返回IServiceScope的方法CreateServiceScope()
 
所以如果你需要实现一个IOC 容器,就要自己实现以上的接口。
 
ServiceLifetime
  • Singleton 单个实例在整个应用程序中
  • Scoped  单个实例在范围窗口内
 
ServiceDescriptor
注册服务的描述信息,
  • ServiceType   用来替换具体实现类的接口,Type类型
  • ImplementationType 上面这个接口的具体实现类型,Type类型
  • Lifetime 服务的生命周期,Singleon,Scoped 或者 Transient
  • ImplementaionFactory 类型Func<IServiceProvider,Object>, 在一些场景中,开发人员希望提供一个工厂方法去创建具体实现类。他们之间是互相独立的,如果你提供了ImplementationType,那不能再提供ImpletentaionFactory.
  • ImplementationInstance 具体事例
 
  Registering Services
现在注册您的服务,ASPNET5希望您 的Startup类中有个叫ConfigureServices的方法名,带有一系列ServiceDescriptors包裹在IServiceCollection,并什么都不返回。你全部只要做的只是创建一系列ServiceDescriptor,并添加他们到集合,web应用程序会在稍后加载他们并注册到容器中

publicvoidConfigureServices(IServiceCollection services)
{
var serviceDescriptor = newServiceDescriptor(typeof(IBankManager), typeof(BankManager), ServiceLifetime.Transient);
services.Add(serviceDescriptor); // Add MVC services to the services container.
services.AddMvc();
}

备注 创建serviceDescriptor有一些繁琐, 这就是你看到一些中间件用扩展方法去创建ServiceDescriptors, 像“service.AddMvc()”

 
下面的伪陈述说明服务启动和ServiceProvider是怎样创建的,相应的代码可以在HostingEngine.Start中找到
 应用程序是如何启动的。
  1. Hosting engine 会创建一个IServiceCollection,是ServiceDescriptor的集合对象
  2. Hosting engine 会添加全部它所需要的服务
  3. Hosting engine 会确认在程序集中有个Startup类,并有个ConfigureServices方法
  4. Hosting engine 会去加载这个方法,并传递IServiceCollection
  5. Startup类中的ConfigureSerivces会添加应用程序需要的服务至集合中
  6. Hosting engine 接着会创建 DefaultServiceProvider(ICO容器),并注册服务集合中IServiceCollection中的服务
  7. Hosting engine 会创建一个应用程序构建器(IApplicationBuilder)并给IApplicationBuilder.ApplicationServices分配一,个新的Service Provider,并进一步的使用它
  8. Hosting engin 在Startup.Configuer执行前会创建一个RequestServicesContainerMiddleware中间件,我会在稍后介绍它
  9. Hosting engine 会执行Startup类中 Configure方法,并传递Application Builder去创建中间件。如果需要Service Provider可通过ApplicationServices属性去创建中间件。
 
 
运行请求

当第一个请求过来时,Httpcontext会被创建并传给第一个Middleware中的Invokde方法中,并会一直传到整个Middleware.但是在处理第一个中间件之前,Application Builder 's Service Provider 会被分配到HttpContext.ApplicationServices,确保整个中间件都可以通过这个属性获得需要的服务,不过,你应该记住这是一个应用程序级别的服务提供者,并且依赖于你选择的Ioc容器,如果你使用了它,你的对象可能会一直驻留在应用程序整个生活周期中.

Notein theory, 理论上,作为一个应用开发人员,你不应该直接去使用这个服务提供者,如果要用建议用Service Locator 模式
 

好吧,这是一个应用程序级别的服务提供者,那有没有每次请求范围里的的服务提供者?

在上面列出来的第8步中,我们提到了Hosting engine 会在管道开始之前会创建一个RequestServicesContainerMiddleware中间件,并会第一时间去执行它
public async Task Invoke(HttpContext httpContext)
{
using(varcontainer = RequestServicesContainer.EnsureRequestServices(httpContext, _services))
{
await_next.Invoke(httpContext);
}
}
  回到上面的请求执行中,服务会创建Httpcontext,并分派给 Application-level Service Provider给HttpContext.ApplicationServices,接着会调用第一个中间件,就是上面的RequestServicesContainerMiddleware,它所做的事情就是创建一个范围内的服务提供者并在请求结束时销毁它
它的伪实现是:
  1. 请求正在被RequestServiceContainerMiddleware处理
  2. Invoke方法会通过application-level Service Provider创建一个IServiceScopeFactory.
  3. IServiceScopeFactory会创建一个范围容器(scoped container)
  4. scoped container会被指派给属性HttpContext.RequestServices
  5. Invoke方法调用接下来的Middleware
  6. 当全部的Middleware都被执行完后,并返回到了RequestServiceContainerMiddleware,Scoped Container会被销毁通过"Using"
 
NoteRequestServicesContainerMiddleware是通过这个包装/帮助类RequestServicesContainer去管理创建和销毁Scoped Service Provider.
 
HttpContext.RequestServices是请求生命周期的范围服务提供者,后来的所有Middle都可以访问它,例如,如果你查看MvcRouteHandler.InvokeActionAsync你会发现它就是通过这个去创建Controller的
 
private async Task InvokeActionAsync(RouteContext context, ActionDescriptor actionDescriptor)
{
var services = context.HttpContext.RequestServices;
Debug.Assert(services != null); var actionContext = new ActionContext(context.HttpContext, context.RouteData, actionDescriptor); var optionsAccessor = services.GetRequiredService<IOptions<MvcOptions>>();
actionContext.ModelState.MaxAllowedErrors = optionsAccessor.Options.MaxModelValidationErrors; var contextAccessor = services.GetRequiredService<IScopedInstance<ActionContext>>();
contextAccessor.Value = actionContext;
var invokerFactory = services.GetRequiredService<IActionInvokerFactory>();
var invoker = invokerFactory.CreateInvoker(actionContext);
if (invoker == null)
{
LogActionSelection(actionSelected: true, actionInvoked: false, handled: context.IsHandled); throw new InvalidOperationException(
Resources.FormatActionInvokerFactory_CouldNotCreateInvoker(
actionDescriptor.DisplayName));
} await invoker.InvokeAsync();
}

ASPNET5 依赖注入(Dependency Injection)的更多相关文章

  1. 控制反转Inversion of Control (IoC) 与 依赖注入Dependency Injection (DI)

    控制反转和依赖注入 控制反转和依赖注入是两个密不可分的方法用来分离你应用程序中的依赖性.控制反转Inversion of Control (IoC) 意味着一个对象不会新创建一个对象并依赖着它来完成工 ...

  2. 简明依赖注入(Dependency Injection)

    前言 这是因特奈特上面不知道第几万篇讲依赖注入(Dependency Injection)的文章,但是说明白的却寥寥无几,这篇文章尝试控制字数同时不做大多数. 首先,依赖注入的是一件很简单的事情. 为 ...

  3. 14.AutoMapper 之依赖注入(Dependency Injection)

    https://www.jianshu.com/p/f66447282780   依赖注入(Dependency Injection) AutoMapper支持使用静态服务定位构建自定义值解析器和自定 ...

  4. 依赖注入 | Dependency Injection

    原文链接: Angular Dependency Injection翻译人员: 铁锚翻译时间: 2014年02月10日说明: 译者认为,本文中所有名词性的"依赖" 都可以理解为 & ...

  5. Spring点滴七:Spring中依赖注入(Dependency Injection:DI)

    Spring机制中主要有两种依赖注入:Constructor-based Dependency Injection(基于构造方法依赖注入) 和 Setter-based Dependency Inje ...

  6. 设计模式之————依赖注入(Dependency Injection)与控制反转(Inversion of Controller)

    参考链接: 依赖注入(DI) or 控制反转(IoC) laravel 学习笔记 —— 神奇的服务容器 PHP 依赖注入,从此不再考虑加载顺序 名词解释 IoC(Inversion of Contro ...

  7. 理解依赖注入(Dependency Injection)

    理解依赖注入 Yii2.0 使用了依赖注入的思想.正是使用这种模式,使得Yii2异常灵活和强大.千万不要以为这是很玄乎的东西,看完下面的两个例子就懂了. class SessionStorage { ...

  8. AngularJS - 依赖注入(Dependency Injection)

    点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ 依赖注入 依赖注入是软件设计模式中的一部分,用于处理组件是如何得到它说依赖的其它组件的. ...

  9. Spring之对象依赖关系(依赖注入Dependency Injection)

    承接上篇: Spring中,如何给对象的属性赋值: 1:通过构造函数,如下所示: <!-- 1:构造函数赋初始值 --><bean id="user1" clas ...

  10. MVC使用StructureMap实现依赖注入Dependency Injection

    使用StructureMap也可以实现在MVC中的依赖注入,为此,我们不仅要使用StructureMap注册各种接口及其实现,还需要自定义控制器工厂,借助StructureMap来生成controll ...

随机推荐

  1. 基础环境之Docker入门

    随着Docker技术的不断成熟,越来越多的企业开始考虑使用Docker.Docker有很多的优势,本文主要讲述了Docker的五个最重要优势,即持续集成.版本控制.可移植性.隔离性和安全性. 有了Do ...

  2. Windows同时安装Python2、Python3兼容运行

    Python2.Python3可以同时安装在windows上,关键是如何有选择的运行Python2还是Python3.   指定运行版本 如果你有一个Python文件叫 hello.py,那么你可以这 ...

  3. 推荐!手把手教你使用Git(转载)

    转载地址http://blog.jobbole.com/78960/,涂根华的博客. Git基本常用命令如下: mkdir:         XX (创建一个空目录 XX指目录名) pwd:      ...

  4. .net 下发送calendar

    前段时间公司系统中有一块需要发送邮件calendar outlook可以接受查看calendar 发送outlook主要是有rrule脚本的边界 网上找过一些资料,主要有两种实现方式 1.一种是已ic ...

  5. (2环境架设)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练

    从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练 1综述http://www.cnblogs.com/jsxyhelu/p/7907241.html2环境架设http://www.cn ...

  6. css3 移动端 开关效果

    展示效果: 首先是html <div class="container"> <div class="bg_con"> <input ...

  7. C#学习笔记-抽象工厂模式

    题目1:数据访问,通过数据库对用户表单的进行访问,数据库包含SQL Server,对用户表单进行“新增用户”和“查询用户”信息等操作. 分析: 首先,确认用户表单,里面包含两个ID和Name两个字段, ...

  8. 软件RAID 0

    软件RAID 0的实现 RAID 0又称为Stripe或Striping,它代表了所有RAID级别中最高的存储性能.RAID 0提高存储性能的原理是把连续的数据分散到多个磁盘上存取,这样,系统有数据请 ...

  9. 【Java】静态代码块使用

    一.java静态代码块与静态方法区别一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调 ...

  10. nautilus出现一闪而过现象

    linux相关问题: 1.这几天在使用乌班图时,出现文件夹打开一闪而过现象,于是我试着使用命令行来启动: sudo nautilus 出现下面这一堆错误(error_info): (nautilus: ...