前言:
如今姐妹们对“aspnet网页打印实例”大体比较看重,同学们都需要剖析一些“aspnet网页打印实例”的相关知识。那么小编也在网络上网罗了一些有关“aspnet网页打印实例””的相关资讯,希望小伙伴们能喜欢,你们一起来学习一下吧!Startup.cs启动前后,做了什么?以及如何从Startup到Webapi/Mvc流程接管?
Startup
UseStartup配置了Startup初始化
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
实际上Startup类是按照IStartup实现的非硬性约束的扩展
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType) {//省略不重要的代码段 return hostBuilder .ConfigureServices(services => { if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo())) { services.AddSingleton(typeof(IStartup), startupType); } else { services.AddSingleton(typeof(IStartup), sp => { var hostingEnvironment = sp.GetRequiredService<IHostEnvironment>(); return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName)); }); } }); }
这里是不是豁然开朗?asp.net core其实内部依赖的是IStartup接口,至于Startup只是一个非IStartup硬性约束的实现
public interface IStartup { IServiceProvider ConfigureServices(IServiceCollection services); void Configure(IApplicationBuilder app); }
Startup类依旧有一定既定约束
1、需要实现ConfigureServices方法,参数为1,且类型为 IServiceCollection,返回值可为void/IServiceProvider(asp.net core 3.0以上,返回值只能为void)
2、需要实现Configure,参数且为生命周期Singleton/Transient的Ioc容器内服务
3、在ConfigureServices方法内配置DI,Configure内启用 中间件
4、启动顺序由ConfigureServices->Configure
中间件
中间件由IApplicationBuilder扩展
常见的IApplicationBuilder.UseMvc就是中间件,其实就是基于Route的一套扩展,本质上webapi/mvc,都是Route上层的一套扩展组件,这块可以翻阅源码,不具体展开了
IApplicationBuilder.Use
下面一段演示示例
app.Use(async (context, next) => { Console.WriteLine("Use"); await next.Invoke(); }); app.Use(async (context, next) => { Console.WriteLine("Use1"); await next.Invoke(); }); app.UseMvc();
先打印Use,然后Use1,最后完成执行。
使用Use方法运行一个委托,我们可以在Next调用之前和之后分别执行自定义的代码,从而可以方便的进行日志记录等工作。这段代码中,使用next.Invoke()方法调用下一个中间件,从而将中间件管道连贯起来;如果不调用next.Invoke()方法,则会造成管道短路。
IApplicationBuilder.Use是IApplicationBuilder Run/Map/MapWhe/Middleware的 核心 模块,基于IApplicationBuilder.Use做各种管道的扩展与实现。
IApplicationBuilder.Run
app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); app.UseMvc();
很简单的示例,在默认api流程前,加了一段输出。段代码中,使用Run方法运行一个委托,这就是最简单的中间件,它拦截了所有请求,返回一段文本作为响应。Run委托终止了管道的运行,因此也叫作中断中间件。
IApplicationBuilder Map/MapWhen
Map创建基于路径匹配的分支、使用MapWhen创建基于条件的分支。
创建一段IApplicationBuilder.Map的示例
app.Map("/api/test", (_map) => { _map.Run(async (conetxt) => { await conetxt.Response.WriteAsync("test"); }); });
访问 /api/test 路由地址时,浏览器输出 test 的字符串。
再编写一段IApplicationBuilder.MapWhen 基于条件的分支示例
app.Map("/api/test", (_map) => { _map.MapWhen((context) => { return context.Request.Path == "/a"; },(__map) => { __map.Run(async (conetxt) => { await conetxt.Response.WriteAsync("test a"); }); }); _map.Run(async (conetxt) => { await conetxt.Response.WriteAsync("test"); }); });
访问 /api/test 路由时,浏览器默认输出 test 字符串,当访问 /api/test/a 路由时,打印 test a 字符串。
Middleware
自定义一个Middleware
public class ContentMiddleware { private RequestDelegate _nextDelegate; public ContentMiddleware(RequestDelegate nextDelegate) { _nextDelegate = nextDelegate; } public async Task Invoke(HttpContext httpContext) { if (httpContext.Request.Path.ToString().ToLower() == "/middleware") { await httpContext.Response.WriteAsync( "Handled by content middleware", Encoding.UTF8); } else { await _nextDelegate.Invoke(httpContext); } } }
访问路由 /middleware, 输出 "Handled by content middleware",反之则管道继续向下运行。
IMiddleware
UseMiddleware内部,判断类是否继承了IMiddleware,是则通过Ioc获取IMiddlewareFactory,通过IMiddlewareFactory 创建,然后在 IApplicationBuilder.Use 运行。
反之则生成表达式在 IApplicationBuilder.Use 运行。
public static IApplicationBuilder UseMiddleware(this IApplicationBuilder app, Type middleware, params object[] args) { if (typeof(IMiddleware).GetTypeInfo().IsAssignableFrom(middleware.GetTypeInfo())) { // IMiddleware doesn't support passing args directly since it's // activated from the container if (args.Length > 0) { throw new NotSupportedException(Resources.FormatException_UseMiddlewareExplicitArgumentsNotSupported(typeof(IMiddleware))); } return UseMiddlewareInterface(app, middleware); } var applicationServices = app.ApplicationServices; return app.Use(next => { //省略代码段 var factory = Compile<object>(methodInfo, parameters); return context => { var serviceProvider = context.RequestServices ?? applicationServices; if (serviceProvider == null) { throw new InvalidOperationException(Resources.FormatException_UseMiddlewareIServiceProviderNotAvailable(nameof(IServiceProvider))); } return factory(instance, context, serviceProvider); }; }); }后记
深挖了一下中间件的相关细节,也查阅了很多作者的分享文章,参考 Asp.Net Core 3.0 源码,重写了一下中间件这块
如果对于内容有交流和学习的
原文地址: