IFoo { }IBar { }Foo : IFoo { }Bar : IBar { }ProgramMain(StartupStartup(IFoo foo)ConfigureServices(IServiceCollection services)Configure(IApplicationBuilder app, IBar bar) 31: { 32: app.Run(async context => 33: { 34: context.Response.ContentType = "text/html"; 35: await context.Response.WriteAsync($"IFoo=>{this.Foo}<br/>"); 36: await context.Response.WriteAsync($"IBar=>{bar}"); 37: }); 38: } 39: }
在Startup的Configure方法中,我们调用ApplicationBulder的Run方法注册了一个Middleware,后者将两个注入的服务的类型作为响应的内容。当我们运行这个应用,并利用浏览器访问默认的监听地址(:5000)时,浏览器会将注入的两个服务对象的类型以下图的方式展现出来。
四、让Startup的ConfigureServices方法返回一个ServiceProvider我们说注册的Startup类型的ConfigureServices允许返回一个ServiceProvider,这个特性的重要意义在于它使我们可以实现与第三方DI框架(比如Unity、Castle、Ninject和AutoFac等)的集成。我们照例采用一个实例对此做一个演示,简单起见,我们并不会真正利用某个具体的DI框架来创建这个ServiceProvider,而是直接创建一个新的ServiceCollection来创建它,为此我们对上面这个程序进行了如下的改写。
ProgramMain(Startup(ServiceDescriptor service Configure(IApplicationBuilder app, IFoo foo, IBar bar) 29: { 30: app.Run(async context => 31: { 32: context.Response.ContentType = "text/html"; 33: await context.Response.WriteAsync($"IFoo=>{foo}<br/>"); 34: await context.Response.WriteAsync($"IBar=>{bar}"); 35: }); 36: } 37: }
如上面的代码片段所示,在Startup的ConfigureServices方法中,我们通过拷贝注册到现有ServiceCollection的所有ServiceDescriptor生成了一个新的ServiceCollection,两个服务Foo和Bar被注册到后者之上。该方法最终返回由这个新ServiceCollection创建的ServiceProvider。在另一个Configure方法中,我们添加了两个类型分别为IFoo和IBar的参数,并以相同的方式将它们的真实类型名称和注册服务类型的映射关系作为响应内容。程序运行之后,我们利用浏览器进行访问照样会得到一样的结果。
五、ASP.NET Core默认注册了哪些服务WebHostBuilder在创建ServiceCollection之后,会注册一些默认的服务。这些服务和我们自行注册的服务并没有任何区别,只要我们知道对应的服务类型,就可以通过注入的方式获取并使用它们。那么具体由哪些服务被默认注册了呢?如下所示的是这些服务对应的类型,至于这些服务各自有何用途,我们在这里就先不深究了。
如果我们需要这些预注册的服务,我们可以按照我们熟悉的方式以依赖注入的方式来使用它们。如下面的代码片段所示,我们在Startup的Configure方法中直接采用方法注入的方式来使用这些预定义的服务。
ProgramMain(StartupConfigure( 15: IApplicationBuilder app, 16: IHostingEnvironment environment, 17: ILoggerFactory loggerFactory, 18: IHttpContextFactory httpContextFactory, 19: DiagnosticSource diagnosticSource, 20: DiagnosticListener diagnosticListener) 21: { 22: app.Run(async context => 23: { 24: context.Response.ContentType = "text/html"; 25: await context.Response.WriteAsync($"IApplicationBuilder=>{app}<br/>"); 26: await context.Response.WriteAsync($"IHostingEnvironment=>{environment}<br/>"); 27: await context.Response.WriteAsync($"ILoggerFactory=>{loggerFactory}<br/>"); 28: await context.Response.WriteAsync($"IHttpContextFactory=>{httpContextFactory}<br/>"); 29: await context.Response.WriteAsync($"DiagnosticSource=>{diagnosticSource}<br/>"); 30: await context.Response.WriteAsync($"DiagnosticListener=>{diagnosticListener}"); 31: }); 32: } 33: }
由于Configure方法注册的Middleware直接将注入服务的注册类型和真实类型的映射关系作为响应内容,所以我们访问应用会的得到如下所示的输出结果。
六、ASP.NET Core MVC中的依赖注入对于ASP.NET MVC 5机器以及之前的版本,在默认情况下定义的Controller都具有一个要求,那就是Controller类型必须具有一个无参数的默认构造函数,否则Controller实例将无法激活。对于自身具有依赖注入功能的ASP.NET Core MVC来说,定义Controller将没有了这个限制。对于预注册的服务,我们完全可以采用构造器注入的方式在定义的Controller中使用它们。作为演示,我们对上面这个应用作了如下的改写。
ProgramMain(HomeControllerIBar Bar { get; .Foo = foo;Index()$"IFoo=>{this.Foo}<br/>IBar=>{this.Bar}"; 33: } 34: }