debugbar

ASP中的许多核心对象。NET的核心框架都是依赖注入提供的,比如用来初始化应用的启动对象和中间件对象,ASP中的控制器对象和视图对象。NET的核心MVC应用,所以我们可以在定义注册服务的时候通过注入来消费它们。下面简单介绍一下服务注入的几种应用场景。本文中的章节选自“揭示ASP。网”。这本书和最后两天打五折。有兴趣的可以扫描右边二维码或者从这里团购。。

一、在Startup类型的构造函数中注入

组成HostBuilderContext上下文的两个核心对象(代表配置的IConfiguration对象和代表宿主环境的IHostEnvironment对象)可以直接注入到启动构造函数中进行消费。由于ASP.NET核心应用中的承载环境是由IWebHostEnvironment接口表示的,而IWebHostEnvironment接口是从IHostEnvironment接口派生出来的,所以通过注入IWebHostEnvironment对象也可以获得当前承载环境的相关信息。

我们可以通过一个简单的例子来验证启动时的构造函数注入。如下面的代码片段所示,我们调用启动程序

类程序{ static void Main() { Host。CreateDefaultBuilder()。ConfigureWebHostDefaults(builder = & gt;建筑商。UseStartup & lt启动& gt()) .构建()。run();} }公共类Startup { public Startup(I configuration configuration,IHostEnvironment hosting environment,IWebHostEnvironment webHostEnvironment){ Debug。断言(配置!= null);调试。Assert(hostingEnvironment!= null);调试。Assert(webHostEnvironment!= null);调试。assert(reference equals(hosting environment,webHostEnvironment));} public void Configure(iapplicationbuilder app){ } }二、将依赖服务注入启动类型Configure方法也可以直接注入用于注册中间件的Configure方法。如果构造函数注入也可以选择注入的服务,那么对于Configure方法,可以注入任何方式注册的服务,包括通过调用IHostBuilder、IWebHostBuilder和Startup本身的ConfigureServices方法注册的服务,以及框架本身注册的所有服务。

如下面的代码片段所示,我们分别调用IWebHostBuilder和Startup的ConfigureServices方法为IFoo接口和IBar接口注册服务,这两个服务直接注入到Startup的Configure方法中。此外,Configure方法需要一个用于注册中间件的IApplicationBuilder对象作为参数,但对该参数出现的位置没有限制。

类程序{ static void Main() { Host。CreateDefaultBuilder()。ConfigureWebHostDefaults(builder = & gt;建筑商。UseStartup & lt启动& gt() .配置服务(svcs = & gtsvcs。AddSingleton & ltIFoo,Foo & gt())) .构建()。run();} }公共类Startup { public void configure services(IServiceCollection services)= & gt;服务。AddSingleton & ltIBar,Bar & gt();public void Configure(IApplicationBuilder app,IFoo foo,IBar bar) { Debug。断言(foo!= null);调试。断言(杠!= null);}}三、将ASP.NET核心请求处理管道注入中间件类型构造器最重要的对象是用来真正处理请求的中间件。因为当ASP.NET核心创建中间件对象并使用它们构建整个请求处理管道时,所有服务都已注册,所以任何注册的服务都可以注入到中间件类型的构造函数中。下面显示的代码片段包含了中间件类型的构造函数注入。

类程序{ static void Main() { Host。CreateDefaultBuilder()。ConfigureWebHostDefaults(builder = & gt;建筑商。配置服务(svcs = & gtsvcs。AddSingleton & ltFoobarMiddleware & gt() .AddSingleton & ltIFoo,Foo & gt() .AddSingleton & ltIBar,Bar & gt()) .配置(app = & gtapp。使用中间件& ltFoobarMiddleware & gt())) .构建()。run();} } public class FoobarMiddleware:IMiddleware { public FoobarMiddleware(IFoo foo,IBar bar) { Debug。断言(foo!= null);调试。断言(杠!= null);}公共任务InvokeAsync(HttpContext context,RequestDelegate next) { Debug。断言(下一个!= null);返回任务。已完成的任务;}} 4.注入到中间件类型的Invoke/InvokeAsync方法中。如果采用基于契约的中间件类型定义方法,注册的服务也可以直接注入到InvokeAsync方法或者真正用于处理请求的Invoke方法中。另外,将方法命名为InvokeAsync更符合TAP(基于任务的异步模式)编程模式,之所以保留命名为Invoke的方法,主要是为了版本兼容的目的。下面显示的代码片段展示了InvokeAsync方法的服务注入。

类程序{ static void Main() { Host。CreateDefaultBuilder()。ConfigureWebHostDefaults(builder = & gt;建筑商。配置服务(svcs = & gtsvcs。AddSingleton & ltIFoo,Foo & gt() .AddSingleton & ltIBar,Bar & gt()) .配置(app = & gtapp。使用中间件& ltFoobarMiddleware & gt())) .构建()。run();} }公共类FoobarMiddleware { private readonly request delegate _ next;public FoobarMiddleware(request delegate next)= & gt;_next =下一个;公共任务InvokeAsync(HttpContext context,IFoo foo,IBar bar) { Debug。断言(上下文!= null);调试。断言(foo!= null);调试。断言(杠!= null);return _next(上下文);}}虽然契约定义的中间件类型和启动类型采用了类似的服务注入方法,都支持构造函数注入和方法注入,但是两者还是有一些区别的。中间件类型的构造函数、启动类型的Configure方法和中间件类型的Invoke方法或InvokeAsync方法都有一个必选参数,其类型分别为RequestDelegate、IApplicationBuilder和HttpContext。这个参数在整个参数列表中的位置没有限制,只有后者要求表示当前请求上下文的参数HttpContext必须是方法的第一个参数。根据上面的约定,下面的中间件类型FoobarMiddleware的定义是非法的,但是Starup类型的定义是合法的。对此,笔者认为可以放宽这一限制,既使得中间件类型的定义更加灵活,又保证了注入方法的一致性。

public类FoobarMiddleware { public FoobarMiddleware(request delegate next);公共任务InvokeAsync(IFoo foo,IBar bar,HttpContext上下文);}公共类启动{ public void Configure(IFoo foo,IBar bar,IApplicationBuilder app);对于基于契约的中间件,构造函数注入和方法注入有本质的区别。由于中间件注册为单例对象,我们不应该将作用域服务注入到它的构造函数中。作用域服务只能注入到中间件类型的InvokeAsync方法中,因为依赖服务是在当前请求的服务作用域中提供的,所以可以保证作用域服务在处理完当前请求后被释放。

五、在Controller类型的构造函数中注入

在ASP.NET核心MVC应用程序中,我们可以通过构造函数注入的方式在定义的控制器中注入所需的服务。在下面显示的代码片段中,我们将IFoobar服务注入HomeController的构造函数中。

类程序{ static void Main() { Host。CreateDefaultBuilder()。ConfigureWebHostDefaults(builder = & gt;建筑商。配置服务(svcs = & gtsvcs。AddSingleton & ltIFoobar,Foobar & gt() .AddSingleton & ltIBar,Bar & gt() .AddControllersWithViews())。配置(app = & gtapp。用户路由()。use endpoints(endpoints = & gt;端点。MapControllers()))))。构建()。run();} } public class home Controller:Controller { public home Controller(IFoobar foobar)= & gt;调试。Assert(foobar!= null);}六。注入控制器的动作方法借助ASP.NET核心MVC基于模型的参数绑定机制,可以将注册的服务绑定到目标动作方法的参数上,进而实现对动作方法的依赖注入。当采用这种类型的注入模式时,我们需要在注入参数上标记如下的FromServicesAttribute特性,以确定参数绑定的来源是注册的服务。

类程序{ static void Main() { Host。CreateDefaultBuilder()。ConfigureWebHostDefaults(builder = & gt;建筑商。配置服务(svcs = & gtsvcs。AddSingleton & ltIFoobar,Foobar & gt() .AddControllersWithViews())。配置(app = & gtapp。用户路由()。use endpoints(endpoints = & gt;端点。MapControllers()))))。构建()。run();} }公共类home Controller:Controller {[http get(& # 34;/")]公共void索引([from services]IFoobar foobar){ Debug。Assert(foobar!= null);}}七。注入到ASP.NET核心MVC应用程序的视图中,我们也可以在当前视图中注册服务。假设我们定义了下面这个简单的MVC程序和一个简单的HomeController。

类程序{ static void Main() { Host。CreateDefaultBuilder()。ConfigureWebHostDefaults(builder = & gt;建筑商。配置服务(svcs = & gtsvcs。AddSingleton & ltIFoobar,Foobar & gt() .AddControllersWithViews())。配置(app = & gtapp。用户路由()。use endpoints(endpoints = & gt;端点。MapControllers()))))。构建()。run();} }公共类home Controller:Controller {[http get(& # 34;/")] public IActionResult Index() = >view();}我们为HomeController定义了一个动作方法索引,路由到根路径(“/”)。该方法在调用View方法呈现默认视图之前,将注入的IFoo服务以视图包的形式传递到视图中。下面显示的代码片段是这个动作方法对应的视图(/Views/Home/Index.cshtml)的定义。我们通过@inject指令注入了IFoobar服务,并将属性名设置为Foobar,这意味着当前视图对象将添加一个Foobar属性来引用注入的服务。

@ inject IFoobar Foobar @ { Debug。Assert(Foobar!= null);}作者:蒋金楠

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论