[Asp.net5]ApplicationBuilder详解

王朝学院·作者佚名  2016-08-28
窄屏简体版  字體: 小  |  中  |  大  |  超大  

applicationBuilder(IApplicationBuilder接口),是OWIN的基础,而且里面都是代理、代理的代理,各种lambda表达式,估计要看这部分代码,很多人得头昏脑涨。今天就对个类以及几个扩展方法进行讲解。

按惯例先贴代码(这是我修改后的,将接口继承去掉了、HttpContext类修改成自己的MyHttpContext类)

[flash=500,400]http://s1.knowsky.com/20160211/l4sjntqmh3o30.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/adh14p5w3ol31.gif[/flash]publicclassApplicationBuilder

{PRivatereadonlyIList<Func<RequestDelegate, RequestDelegate>> _components =newList<Func<RequestDelegate, RequestDelegate>>();publicApplicationBuilder() { }privateApplicationBuilder(ApplicationBuilder builder)

{

}publicApplicationBuilder Use(Func<RequestDelegate, RequestDelegate>middleware)

{

_components.Add(middleware);returnthis;

}publicApplicationBuilder New()

{returnnewApplicationBuilder(this);

}publicRequestDelegate Build()

{

RequestDelegate app= context =>{

context.StatusCode="404";

System.Console.WriteLine("404");returnTask.FromResult(0);

};foreach(varcomponentin_components.Reverse())

{

app=component(app);

}returnapp;

}

}

View Code

RequestDelegate的定义如下:

publicdelegateTask RequestDelegate(MyHttpContext context);

从ApplicationBuilder的源代码中我们可以关注3个点:_components、Use方法、Build方法。

_components是也一个列表(IList)对象,不过里面类型有点特殊——是以代理RequestDelegate为参数、代理RequestDelegate为返回值的一个代理。这里用代理说有点别嘴,可以把代理叫做函数,就是里面的类型是一个函数,这个函数的参数也是函数,返回值也是函数。Use方法,就是在上面的列表对象后面添加一条新记录。Build方法就是将_components数组按照反向顺序,制作成一个链式结构(有点类似链表的感觉)。下面用俩幅图说明下:Build之前

[flash=500,400]http://s1.knowsky.com/20160211/tlrkhxbmyb031.png[/flash]

Build之后

[flash=500,400]http://s1.knowsky.com/20160211/3wy2vsfmbb131.png[/flash]

我们还可以从代码中看到Item1的参数给的是“404”,而返回结果是RequestDelegate类型。也就是说这个返回类似于void RequestDelegate(MyHttpContext context)。如果系统给我们一个context变量,那么这个管道就可以从头到尾的跑下去了。而事实上在asp.net5中,这个管道就是用于替代传统的IHttpModule的(可能不准确),那现在问题就来了,Item1的参数是这个管道的第一环还是最后一环呢?从图形来看应该是第一环,但是事实上这是一个误解。因为箭头两面一个是参数,一个是执行体(参数是一个方法,会在执行体内调用执行)。在执行体内,可能在开始就执行参数的内容,之后执行具体的内容;也可以是先执行具体内容,之后执行参数,最后在执行一部分具体内容;还可以先执行具体内容,之后参数;还可能无视参数,直接直接自己的内容,那么之前的参数就会被忽略。也就是说无所谓顺序,404可能是管道的第一环,也可能是最后一环,也可能是中间环节,还可能压根就不执行。这个和Item1、Item2等内容具体的写法有关系。(虽然也是链式结构是不是和链表感觉不一样)

是不是感觉太零活了,源码还对ApplicationBuilder做了俩个扩展方法,代码整理如下:

[flash=500,400]http://s1.knowsky.com/20160211/l4sjntqmh3o30.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/adh14p5w3ol31.gif[/flash]publicstaticclassRunExtensions

{publicstaticApplicationBuilder Use(thisApplicationBuilder app, Func<MyHttpContext, Func<Task>, Task>middleware)

{returnapp.Use(next =>{returncontext =>{

Func<Task> simpleNext = () =>next(context);returnmiddleware(context, simpleNext);

};

});

}publicstaticvoidRun(thisApplicationBuilder app, RequestDelegate handler)

{if(app ==null)

{thrownewArgumentNullException("why?");

}if(handler ==null)

{thrownewArgumentNullException("How?");

}

app.Use(_=>handler);

}

}

View Code

首先说Use方法,改方法是对之前Use方法的一个更改。将传入的参数更改为 Func<MyHttpContext, Func<Task>, Task>。这样做有什么好处?之前的Func<RequestDelegate, RequestDelegate>对象并不能给人清楚的明了的感觉,而Func<MyHttpContext, Func<Task>, Task>就非常明确了。传入的参数:MyHttpContext就是Context对象,Func<Task>就是next的执行体。返回值是一个Task(类似于void)。一目了然。

再说Run方法,显而易见,Run方法只执行自己的内容,并没有执行参数体。所以链式结构的在其前的都会被舍弃,不会被执行。

最后把自己的测试例子贴出来,供大家参考

示例1:

[flash=500,400]http://s1.knowsky.com/20160211/l4sjntqmh3o30.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/adh14p5w3ol31.gif[/flash]staticvoidMain(string[] args)

{

MyHttpContext context=newMyHttpContext() { StatusCode ="A"};

Func<MyHttpContext, Func<Task>, Task> middleware =(x, y)=> { context.StatusCode +="C"; System.Console.WriteLine(context.StatusCode);returny(); };

Func<MyHttpContext, Func<Task>, Task> middleware2 =(x, y)=> { context.StatusCode +="End1"; System.Console.WriteLine(context.StatusCode);returnTask.FromResult(0); };

ApplicationBuilder builder=newApplicationBuilder();

builder.Use(

next=>{return(MyHttpContext o) =>{

o.StatusCode+="B";

System.Console.WriteLine(context.StatusCode);

next(o);returnTask.FromResult(0);

};

}

);

builder.Use(middleware);//builder.Use(middleware2);//builder.Use(middleware);//builder.Run(o => { o.StatusCode += "End2"; return Task.FromResult(0); });builder.Build().Invoke(context);

System.Console.ReadLine();

}

View Code

执行结果:[flash=500,400]http://s1.knowsky.com/20160211/gjetfohdteg31.png[/flash]

示例2:

[flash=500,400]http://s1.knowsky.com/20160211/l4sjntqmh3o30.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/adh14p5w3ol31.gif[/flash]staticvoidMain(string[] args)

{

MyHttpContext context=newMyHttpContext() { StatusCode ="A"};

Func<MyHttpContext, Func<Task>, Task> middleware =(x, y)=> { context.StatusCode +="C"; System.Console.WriteLine(context.StatusCode);returny(); };

Func<MyHttpContext, Func<Task>, Task> middleware2 =(x, y)=> { context.StatusCode +="End1"; System.Console.WriteLine(context.StatusCode);returnTask.FromResult(0); };

ApplicationBuilder builder=newApplicationBuilder();

builder.Use(

next=>{return(MyHttpContext o) =>{

o.StatusCode+="B";

System.Console.WriteLine(context.StatusCode);

next(o);returnTask.FromResult(0);

};

}

);

builder.Use(middleware);

builder.Use(middleware2);//builder.Use(middleware);//builder.Run(o => { o.StatusCode += "End2"; System.Console.WriteLine(context.StatusCode); return Task.FromResult(0); });builder.Build().Invoke(context);

System.Console.ReadLine();

}

View Code

执行结果:[flash=500,400]http://s1.knowsky.com/20160211/khc0axqsvhi31.png[/flash]

示例3:

[flash=500,400]http://s1.knowsky.com/20160211/l4sjntqmh3o30.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/adh14p5w3ol31.gif[/flash]staticvoidMain(string[] args)

{

MyHttpContext context=newMyHttpContext() { StatusCode ="A"};

Func<MyHttpContext, Func<Task>, Task> middleware =(x, y)=> { context.StatusCode +="C"; System.Console.WriteLine(context.StatusCode);returny(); };

Func<MyHttpContext, Func<Task>, Task> middleware2 =(x, y)=> { context.StatusCode +="End1"; System.Console.WriteLine(context.StatusCode);returnTask.FromResult(0); };

ApplicationBuilder builder=newApplicationBuilder();

builder.Use(

next=>{return(MyHttpContext o) =>{

o.StatusCode+="B";

System.Console.WriteLine(context.StatusCode);

next(o);returnTask.FromResult(0);

};

}

);

builder.Use(middleware);//builder.Use(middleware2);//builder.Use(middleware);builder.Run(o => { o.StatusCode +="End2"; System.Console.WriteLine(context.StatusCode);returnTask.FromResult(0); });

builder.Build().Invoke(context);

System.Console.ReadLine();

}

View Code

执行结果:[flash=500,400]http://s1.knowsky.com/20160211/jxor4rlmwfm32.png[/flash]

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航