设为首页 加入收藏

TOP

一步步完成“迷你版” 的ASP.NET Core框架(二)
2019-09-17 18:23:56 】 浏览:96
Tags:步步 完成 迷你 ASP.NET Core 框架
eFeature.Headers; public Stream Body => _httpResponseFeature.Body; } public static partial class Extensions { public static Task WriteAsync(this HttpResponse response,string content) { var buffer = Encoding.UTF8.GetBytes(content); return response.Body.WriteAsync(buffer, 0, buffer.Length); } }

定义处理器

封装好了HttpContext,终于可以回过头来看看处理器。
处理器的处理方法现在应该是这样:

  Task Handle(HttpContext context);

接下来就是怎么定义这个处理器了。
起码有两种方式:
1、定义一个接口:

    public interface IHttpHandler
    {
        Task Handle(HttpContext context);
    }

2、定义一个委托类型

public delegate Task RequestDelegate(HttpContext context);

两种方式,本质上没啥区别,委托代码方式更灵活,不用实现一个接口,还符合鸭子模型。
处理器就选用委托类型。
定义了处理器,接下来看看服务器

四 服务器的抽象

服务器应该有一个开始方法,传入处理器,并执行。
服务器抽象如下:

    public interface IServer
    {
        Task StartAsync(RequestDelegate handler);
    }

定义一个HttpListener的服务器来实现IServer,由于HttpListener的服务器需要提供HttpContext所需的数据,所以先定义HttpListenerFeature

    public class HttpListenerFeature : IHttpRequestFeature, IHttpResponseFeature
    {

        private readonly HttpListenerContext _context;

        public HttpListenerFeature(HttpListenerContext context) => _context = context;
        Uri IHttpRequestFeature.Url => _context.Request.Url;

        Nameva lueCollection IHttpRequestFeature.Headers => _context.Request.Headers;

        Nameva lueCollection IHttpResponseFeature.Headers => _context.Response.Headers;

        Stream IHttpRequestFeature.Body => _context.Request.InputStream;

        Stream IHttpResponseFeature.Body => _context.Response.OutputStream;

        int IHttpResponseFeature.StatusCode
        {
            get => _context.Response.StatusCode;
            set => _context.Response.StatusCode = value;
        }
    }

定义HttpListener服务器

  public class HttpListenerServer : IServer
    {
        private readonly HttpListener _httpListener;

        private readonly string[] _urls;

        public HttpListenerServer(params string[] urls)
        {
            _httpListener = new HttpListener();
            _urls = urls.Any() ? urls : new string[] { "http://localhost:5000/" };
        }
        public async Task StartAsync(RequestDelegate handler)
        {
            Array.ForEach(_urls, url => _httpListener.Prefixes.Add(url));

            _httpListener.Start();
            Console.WriteLine($"服务器{typeof(HttpListenerServer).Name} 开启,开始监听:{string.Join(";", _urls)}");
            while (true)
            {
                var listtenerContext = await _httpListener.GetContextAsync();
                var feature = new HttpListenerFeature(listtenerContext);

                var features = new FeatureCollection()
                    .Set<IHttpRequestFeature>(feature)
                    .Set<IHttpResponseFeature>(feature);
                var httpContext = new HttpContext(features);

                await handler(httpContext);

                listtenerContext.Response.Close();
            }
        }
    }

修改Main方法运行测试

        static async Task Main(string[] args)
        {
            IServer server = new HttpListenerServer();
            async Task FooBar(HttpContext httpContext)
            {
                await httpContext.Response.WriteAsync("fooBar");
            }
            await server.StartAsync(FooBar); 
        }

运行结果如下:

至此,完成了服务器和处理器的抽象。
接下来单看处理器,所有的处理逻辑都集合在一个方法中,理想的方式是有多个处理器进行处理,比如处理器A处理完,则接着B处理器进行处理……
那么就要管理多个处理器之间的连接方式。

五 中间件

中间件的定义

假设有三个处理器A,B,C
框架要实现:A处理器开始处理,A处理完成之后,B处理器开始处理,B处理完成之后,C处理器开始处理。

引入中间件来完成处理器的连接。

中间件的要实现的功能很简单:

  • 传入下一个要执行的处理器;
  • 在中间件中的处理器里,记住下一个要执行的处理器;
  • 返回中间件中的处理器,供其他中间件使用。
    所以中间件应该是这样的:
 //伪代码
 处理器  Middleware(传入下一个要执行的处理器)
 {
     return 处理器
     {
         //处理器的逻辑
         下一个要执行的处理器在这里执行
     }
 }

举个例子,现在有三个中间件FooMiddleware,BarMiddleware,BazMiddlewa

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C# 中类的成员有哪些? 下一篇dotnet core 之 CORS使用示例

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目