详解Asp.net 5中的ApplicationBuilder

2022-04-16 16:26:58

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 Use(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.Reverse())            {                app = component(app);            }            return app;        }    }

RequestDelegate的定义如下:

public delegate Task RequestDelegate(MyHttpContext context);

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

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

Build之前

{ throw new ArgumentNullException("How?"); } app.Use(_ => handler); } }

首先说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:

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.Use(                next =>                {                    return (MyHttpContext o) =>                    {                        o.StatusCode += "B";                        System.Console.WriteLine(context.StatusCode);                        next(o);                        return Task.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();        }

执行结果:

详解Asp.net 5中的ApplicationBuilder

示例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.Use(                next =>                {                    return (MyHttpContext o) =>                    {                        o.StatusCode += "B";                        System.Console.WriteLine(context.StatusCode);                        next(o);                        return Task.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();        }

执行结果:

详解Asp.net 5中的ApplicationBuilder

示例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); };            ApplicationBuilder builder = new ApplicationBuilder();            builder.Use(                next =>                {                    return (MyHttpContext o) =>                    {                        o.StatusCode += "B";                        System.Console.WriteLine(context.StatusCode);                        next(o);                        return Task.FromResult(0);                    };                }            );            builder.Use(middleware);            //builder.Use(middleware2);            //builder.Use(middleware);            builder.Run(o => { o.StatusCode += "End2"; System.Console.WriteLine(context.Statwww.easck.comusCode); return Task.FromResult(0); });            builder.Build().Invoke(context);            System.Console.ReadLine();        }

执行结果:

详解Asp.net 5中的ApplicationBuilder

 到此这篇关于详解Asp.net 5中的ApplicationBuilder的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。