applicationbuilder(iapplicationbuilder接口),是owin的基础,而且里面都是代理、代理的代理,各种lambda表达式,估计要看这部分代码,很多人得头昏脑涨。今天就对个类以及几个扩展方法进行讲解。
按惯例先贴代码(这是我修改后的,将接口继承去掉了、httpcontext类修改成自己的myhttpcontext类)
public class applicationbuilder { private readonly ilist<func<requestdelegate, requestdelegate>> _components = new list<func<requestdelegate, requestdelegate>>(); public applicationbuilder() { } private applicationbuilder(applicationbuilder builder) { } public applicationbuilder u(func<requestdelegate, requestdelegate> middleware) { _components.add(middleware); return this; } public applicationbuilder new() { return new applicationbuilder(this); } public requestdelegate build() { requestdelegate app = context => { context.statuscode = "404"; system.console.writeline("404"); 文学摘抄 return task.fromresult(0); }; foreach (var component in _components.rever()) { app = component(app); } return app; } }
requestdelegate的定义如下:
public delegate task requestdelegate(myhttpcontext context);
从applicationbuilder的源代码中我们可以关注3个点:_components、u方法、build方法。
_components是也一个列表(ilist)对象,不过里面类型有点特殊——是以代理requestdelegate为参数、代理requestdelegate为返回值的一个代理。这里用代理说有点别嘴,可以把代理叫做函数,就是里面的类型是一个函数,这个函数的参数也是函数,返回值也是函数。u方法,就是在上面的列表对象后面添加一条新记录。build方法就是将_components数组按照反向顺序,制作成一个链式结构(有点类似链表的感觉)。下面用俩幅图说明下:build之前
build之后
我们还可以从代码中看到item1的参数给的是“404”,而返回结果是requestdelegate类型。也就是说这个返回类似于voidrequestdelegate(myhttpcontext context)。如果系统给我们一个context变量,那么这个管道就可以从头到尾的跑下去了。而事实上在asp.net5中,这个管道就是用于替代传统的ihttpmodule的(可能不准确),那现在问题就来了,item1的参数是这个管道的第一环还是最后一环呢?从图形来看应该是第一环,但是事实上这是一个误解。因为箭头两面一个是参数,一个是执行体(参数是一个方法,会在执行体内调用执行)。在执行体内,可能在开始就执行参数的内容,之后执行具体的内容;也可以是先执行具体内容,之后执行参数,最后在执行一部分具体内容;还可以先执行具体内容,之后参数;还可能无视参数,直接直接自己的内容,那么之前的参数就会被忽略。也就是说无所谓顺序,404可能是管道的第一环,也可能是最后一环,也可能是中间环节,还可能压根就不执行。这个和item1、item2等内容具体的写法有关系。(虽然也是链式结构是不是和链表感觉不一样)
是不是感觉太零活了,源码还对applicationbuilder做了俩个扩展方法,代码整理如下:
public static class runextensions { public static applicationbuilder u(this applicationbuilder app, func<myhttpcontext, func<task>, task> middleware) { return app.u(next => { return context => { func<task> simplenext = () => next(context); return middleware(context, simplenext); }; }); } public static void run(this applicationbuilder app, requestdelegate handler) { if (app == null) { throw new argumentnullexception("why?"); } if (handler == null) { throw new argumentnullexception("how?"); } app.u(_ => handler); } }
首先说u方法,改方法是对之前u方法的一个更改。将传入的参数更改为func<myhttpcontext, func<task>, task>。这样做有什么好处?之前的func<requestdelegate, requestdelegate>对象并不能给人清楚的明了的感觉,而func<myhttpcontext, func<task>, task>就非常明确了。传入的参数:myhttpcontext就是context对象,func<task>就是next的执行体。返回值是一个task(类似于void)。一目了然。
再说run方法,显而易见,run方法只执行自己的内容,并没有执行参数体。所以链式结构的在其前的都会被舍弃,不会被执行。
最后把自己的测试例子贴出来,供大家参考
示例1:
static void main(string[] args) { myhttpcontext context = new myhttpcontext() { statuscode = "a" }; func<myhttpcontext, func<task>, task> middleware = (x, y) => { context.statuscode += "c"; system.console.writeline(context.statuscode); return y(); }; func<myhttpcontext, func<task>, task> middleware2 = (x, y) => { context.statuscode += "end1"; system.console.writeline(context.statuscode); return task.fromresult(0); }; applicationbuilder builder = new applicationbuilder(); builder.u( next => { return (myhttpcontext o) => { o.st书记述职述廉报告atuscode += "b"; system.console.writeline(context.statuscode); next(o); return task.fromresult(0); }; 国歌叫什么名字 } ); builder.u(middleware); //builder.u(middleware2); //builder.u(middleware); //builder.run(o => { o.statuscode += "end2"; return task.fromresult(0); }); builder.build().invoke(context); system.console.readline(); }
执行结果:
示例2:
static void main(string[] args) { myhttpcontext context = new myhttpcontext() { statuscode = "a" }; func<myhttpcontext, func<task>, task> middleware = (x, y) => { context.statuscode += "c"; system.console.writeline(context.statuscode); return y(); }; func<myhttpcontext, func<task>, task> middleware2 = (x, y) => { context.statuscode += "end1"; system.console.writeline(context.statuscode); return task.fromresult(0); }; applicationbuilder builder = new applicationbuilder(); builder.u( next => { return (myhttpcontext o) => { o.statuscode += "b"; system.console.writeline(context.statuscode); next(o)自称是什么意思; return task.fromresult(0); }; } ); builder.u(middleware); builder.u(middleware2); //builder.u(middleware); //builder.run(o => { o.statuscode += "end2"; system.console.writeline(context.statuscode); return task.fromresult(0); }); builder.build().invoke(context); system.console.readline(); }
执行结果:
示例3:
static void main(string[] args) { myhttpcontext context = new myhttpcontext() { statuscode = "a" }; func<myhttpcontext, func<task>, task> middleware = (x, y) => { context.statuscode += "c"; system.console.writeline(context.statuscode); return y(); }; func<myhttpcontext, func<task>, task> middleware2 = (x, y) => { context.statuscode += "end1"; system.console.writeline(context.statuscode); return task.fromresult(0); }; ap临江仙苏轼plicationbuilder builder = new applicationbuilder(); builder.u( next => { return (myhttpcontext o) => { o.statuscode += "b"; system.console.writeline(context.statuscode); next(o); return task.fromresult(0); }; } ); builder.u(middleware); //builder.u(middleware2); //builder.u(middleware); builder.run(o => { o.statuscode += "end2"; system.console.writeline(context.statuscode); return task.fromresult(0); }); builder.build().invoke(context); system.console.readline(); }
执行结果:
到此这篇关于详解asp.net 5中的applicationbuilder的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。
本文发布于:2023-04-04 14:19:08,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/ab4ed001400ad4092d3daa7dfae37a99.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:详解Asp.net 5中的ApplicationBuilder.doc
本文 PDF 下载地址:详解Asp.net 5中的ApplicationBuilder.pdf
留言与评论(共有 0 条评论) |