男人女人做爰教程,张家界天气预报查询,luotimeinvxiezhen
public class middleware { private readonly requestdelegate _next; public routermiddleware(requestdelegate next) { _next = next; } public async task invoke(httpcontext httpcontext) { // do something await _next.invoke(httpcontext); // do something } }
namespace microsoft.aspnetcore.builder.internal { public class applicationbuilder : iapplicationbuilder { private readonly ilist<func<requestdelegate, requestdelegate>> _components = new list<func<requestdelegate, requestdelegate>>(); public iapplicationbuilder use(func<requestdelegate, requestdelegate> middleware) { _components.add(middleware); return this; } } }
applicationbuilder.build
方法会处理所有注册的中间件生成的委托集合,将所有中间件生成的委托集合,处理成嵌套的形式,最终得到一个委托,连成一段管道。reverse
方法将集合反转,从最后注册的中间件对应的委托开始处理startup.cs
类里面的configure
方法,里面的每个use开头的方法都对应一个中间件注册,代码的顺序就是注册的顺序,也是执行的顺序,千万不能写错了。因为mvc处于处理流程的最后面,因此usemvc方法总是位于最后component
,是从_components
委托集合里面取出来的,执行后又得到一个requestdelegate
类型的委托,因此由中间件生成的委托的类型应该是func<requestdelegate, requestdelegate>
public requestdelegate build() { requestdelegate app = context => { context.response.statuscode = 404; return task.completedtask; }; foreach (var component in _components.reverse()) { app = component(app); } return app; }
applicationbuilder.use
方法,将中间件生成的委托加入委托集合,完成中间件注册app.use
方法参数,就是上面需要的类型func<requestdelegate, requestdelegate>
的委托,该委托的参数next
就是下一个中间件对应的委托,返回值就是中间件的invoke
方法对应的委托,该方法用到了next
public static iapplicationbuilder usemiddleware<tmiddleware>(this iapplicationbuilder app, params object[] args) { return app.usemiddleware(typeof(tmiddleware), args); } public static iapplicationbuilder usemiddleware(this iapplicationbuilder app, type middleware, params object[] args) { // 省略部分代码 var applicationservices = app.applicationservices; return app.use(next => { // 省略部分代码 var ctorargs = new object[args.length + 1]; ctorargs[0] = next; array.copy(args, 0, ctorargs, 1, args.length); var instance = activatorutilities.createinstance(app.applicationservices, middleware, ctorargs); if (parameters.length == 1) { return (requestdelegate)methodinfo.createdelegate(typeof(requestdelegate), instance); } 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); }; }); }
imiddleware
接口,则调用usemiddlewareinterface
方法。使用了接口规范,那么你也不能乱写了,只需要注意在invoke
方法调用next
即可private static iapplicationbuilder usemiddlewareinterface(iapplicationbuilder app, type middlewaretype) { return app.use(next => { return async context => { var middlewarefactory = (imiddlewarefactory)context.requestservices.getservice(typeof(imiddlewarefactory)); if (middlewarefactory == null) { // no middleware factory throw new invalidoperationexception(resources.formatexception_usemiddlewarenomiddlewarefactory(typeof(imiddlewarefactory))); } var middleware = middlewarefactory.create(middlewaretype); if (middleware == null) { // the factory returned null, it's a broken implementation throw new invalidoperationexception(resources.formatexception_usemiddlewareunabletocreatemiddleware(middlewarefactory.gettype(), middlewaretype)); } try { await middleware.invokeasync(context, next); } finally { middlewarefactory.release(middleware); } }; }); }
invoke
或invokeasync
的一个方法public static class usemiddlewareextensions { internal const string invokemethodname = "invoke"; internal const string invokeasyncmethodname = "invokeasync"; } var invokemethods = methods.where(m => string.equals(m.name, invokemethodname, stringcomparison.ordinal) || string.equals(m.name, invokeasyncmethodname, stringcomparison.ordinal) ).toarray();
if (invokemethods.length > 1) { throw new invalidoperationexception(resources.formatexception_usemiddlemutlipleinvokes(invokemethodname, invokeasyncmethodname)); } if (invokemethods.length == 0) { throw new invalidoperationexception(resources.formatexception_usemiddlewarenoinvokemethod(invokemethodname, invokeasyncmethodname, middleware)); }
task
var methodinfo = invokemethods[0]; if (!typeof(task).isassignablefrom(methodinfo.returntype)) { throw new invalidoperationexception(resources.formatexception_usemiddlewarenontaskreturntype(invokemethodname, invokeasyncmethodname, nameof(task))); }
httpcontext
var parameters = methodinfo.getparameters(); if (parameters.length == 0 || parameters[0].parametertype != typeof(httpcontext)) { throw new invalidoperationexception(resources.formatexception_usemiddlewarenoparameters(invokemethodname, invokeasyncmethodname, nameof(httpcontext))); }
usemiddleware
方法传入的自定义参数args
加上下一个委托next
,得到新的参数数组,然后创建中间件实例,生成invoke
方法对应委托。此处注意,如果中间件的构造函数中有其它参数,但是未注册到applicationservices
的话,需要在usemiddleware
方法中传入var ctorargs = new object[args.length + 1]; ctorargs[0] = next; array.copy(args, 0, ctorargs, 1, args.length); var instance = activatorutilities.createinstance(app.applicationservices, middleware, ctorargs); if (parameters.length == 1) { return (requestdelegate)methodinfo.createdelegate(typeof(requestdelegate), instance); }
compile
方法,生成一个委托,该委托从iserviceprovider
中获取需要的参数的实例,再调用invoke
方法,相比上面的情况,多了一步从iserviceprovider
获取实例,注入到invoke
而已。compile
方法使用了linq表达式树,源码位于microsoft.aspnetcore.builder.usemiddlewareextensions,此处不作讲解,因为我也不太懂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); };
最后,文章可能有更新,请阅读原文获得更好的体验哦
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Net Core Web Api项目与在NginX下发布的方法
asp.net core3.1 引用的元包dll版本兼容性问题解决方案
IdentityServer4实现.Net Core API接口权限认证(快速入门)
ASP.NET Core MVC通过IViewLocationExpander扩展视图搜索路径的实现
网友评论