Read the source code middleware explore achieve NetCore

1. Look at the code in the Core2.2 Startup, the Configure method writes middleware, app.Use

 
 1 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
 2 {
 3     #region Middleware
 4     app.Use(next =>
 5     {
 6         Console.WriteLine("this is Middleware1");
 7         return new RequestDelegate(async context =>
 8         {
 9             context.Response.ContentType = "text/html; charset=utf-8";
10             await context.Response.WriteAsync("<span><h3>This is Middleware1 start</h3></span>");
11             await next.Invoke(context);
12             await context.Response.WriteAsync("<span><h3>This is Middleware1 end</h3></span>");
13         });
14     });
15     app.Use(next =>
16     {
17         return new RequestDelegate(async context =>
18         {
19             await context.Response.WriteAsync("<span><h3>This is Middleware2 start</h3></span>");
20             await next.Invoke(context);
21             await context.Response.WriteAsync("<span><h3>This is Middleware2 end</h3></span>");
22         });
23     });
24     app.Use(next =>
25     {
26         Console.WriteLine("this is Middleware3");
27         return new RequestDelegate(async context =>
28         {
29             await context.Response.WriteAsync("<span><h3>This is Middleware3 start</h3></span>");
30             await next.Invoke(context);
31             await context.Response.WriteAsync("<span><h3>This is Middleware3 end</h3></span>");
32         });
33     });
34     app.Run(async context => await context.Response.WriteAsync("跑完了.")); //这一句得加上,才能看出
35     #endregion
36 
37 
38 
39     if (env.IsDevelopment())
40         app.UseDeveloperExceptionPage();
41     else
42     {
43         app.UseExceptionHandler("/Home/Error");
44         // The default HSTS value is 30 days. You may want to change this for production scenarios, see 
45         app.UseHsts();
46     }
47 
48     app.UseHttpsRedirection();
49     app.UseStaticFiles();
50     app.UseCookiePolicy();
51 
52     app.UseMvc(routes =>
53     {
54         routes.MapRoute(
55             name: "default",
56             template: "{controller=Home}/{action=Index}/{id?}");
57     });
58 }
 

2. Run the debugging output

 

3. By looking at the source code, in fact, that app.Use method to add a Func delegate to IList <Func <RequestDelegate, RequestDelegate >>

 

public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
    //_components 就是这个 private readonly IList<Func<RequestDelegate, RequestDelegate>> _components 
    //= new List<Func<RequestDelegate, RequestDelegate>>();
   _components.Add(middleware);// _components 
   return this;
}

 

See middleware processing logic code
 1 public RequestDelegate Build()
 2 {
 3     RequestDelegate app = context =>
 4     {
 5         // If we reach the end of the pipeline, but we have an endpoint, then something unexpected has happened.
 6         // This could happen if user code sets an endpoint, but they forgot to add the UseEndpoint middleware.
 7         var endpoint = context.GetEndpoint();
 8         var endpointRequestDelegate = endpoint?.RequestDelegate;
 9         if (endpointRequestDelegate != null)
10         {
11             var message =
12                 $"The request reached the end of the pipeline without executing the endpoint: '{endpoint.DisplayName}'. " +
13                 $"Please register the EndpointMiddleware using '{nameof(IApplicationBuilder)}.UseEndpoints(...)' if using " +
14                 $"routing.";
15             throw new InvalidOperationException(message);
16         }
17 
18         context.Response.StatusCode = 404;
19         return Task.CompletedTask;
20     };
21 
22     foreach (var component in _components.Reverse())
23     {
24         app = component(app);
25     }
26 
27     return app;
28 }
Through this source can be found throughout the middleware processing logic is all set to the middleware is stored _components , this core is set, it is converted into a single delegate RequestDelege . Convenient caller invokes a method performs commissioned inside.
By means of this thoughts and ideas, to write their own demo
Create a new Core test program:
 
namespace Test
{
    /// <summary>
    /// 给入字符串,返回 Task
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public delegate Task Conduit(string str);


    public class MiddlewareDemo
    {
        [Test]
        public void Implement()
        {
            CustomMiddleware middle = new CustomMiddleware();

            #region C

            middle.Add(next =>
            {
                return zfc =>
               {
                   Console.WriteLine ( " The first phase starts " );
                   System.Diagnostics.Debug.WriteLine ( " The first phase starts " );
                    return the Next (ZFC);
               };
            });

            middle.Add(next =>
            {
                return zfc =>
               {
                   Console.WriteLine ( " second phase starts " );
                   System.Diagnostics.Debug.WriteLine ( " second phase starts " );
                    return the Next (ZFC);
               };
            });

            middle.Add(next =>
            {
                return zfc =>
               {
                   Console.WriteLine ( " third phase starts " );
                   System.Diagnostics.Debug.WriteLine ( " third phase starts " );
                    return the Next (ZFC);
               };
            });

            #endregion


            #region D
             // middle.Add (Next =>
             // {
             //     return the async = ZFC>
             //     {
             //         Console.WriteLine ( "first phase starts");
             //         System.Diagnostics.Debug.WriteLine ( " The first phase starts ");
             //         the await Next (ZFC);
             //         Console.WriteLine (" end of the first phase ");
             //         System.Diagnostics.Debug.WriteLine (" end of the first phase ");
             //     } ;
             // });

            // middle.Add (Next =>
             // {
             //     return the async = ZFC>
             //     {
             //         Console.WriteLine ( "second phase starts");
             //         System.Diagnostics.Debug.WriteLine ( "the second stage start ");
             //         the await Next (ZFC);
             //         System.Diagnostics.Debug.WriteLine (" end of the second phase ");
             //         Console.WriteLine (" end of the second phase ");
             //     };
             // });

            // middle.Add (Next =>
             // {
             //     return the async = ZFC>
             //     {
             //         Console.WriteLine ( "third phase starts");
             //         System.Diagnostics.Debug.WriteLine ( "third stage start ");
             //         the await the Next (ZFC);
             //         System.Diagnostics.Debug.WriteLine (" the end of the third stage ");
             //         Console.WriteLine (" the end of the third stage ");
             //     };
             // }); 
            #endregion 
            var AK = middle.GetDelegate ();
            ak.Invoke ( " n-order execution middleware " );
        System.Diagnostics.Debug.WriteLine ( " ********** boundary ********** " );
             var FF = middle.Reverse ();
            ff.Invoke ( " started middleware! " );

            System.Diagnostics.Debug.WriteLine ( " finish the ddd " );
            Console.WriteLine ( " finish the ddd " );

        }
    }


    ///  <Summary> 
    /// analog intermediate
     ///  </ Summary> 
    public  class CustomMiddleware
    {
        public the IList <Func <the Conduit, the Conduit >> _middlelist = new new List <Func <the Conduit, the Conduit >> ();
         // the Add i.e. NetCore in the StartUp app.Use, empathy      
        public  void the Add (Func <the Conduit, the Conduit > FUNC)
        {
            _middlelist.Add(func);
        }

        // In order to facilitate understanding of comparison, this is not a set of reverse
         // to integrate into a set of Conduit commissioned 
        public Conduit getDelegate ()
        {
            Conduit led = str =>
             {
                 str = " initialized! " ;
                  return Task.CompletedTask;
             };
            foreach (Func <Conduit, Conduit> Item in _middlelist) // positive sequence
               // core here, seemingly in assigning new values, in fact, is wrapped in layer after layer of a method of performing this instance,
               // giving the impression it as in superposition, if this place does not reverse, the execution order of the method is the opposite 
               Conduit = Item (Conduit); 
             return Conduit;
        }


        ///  <Summary> 
        /// the collection flashback, then integrated into a delegate Conduit
         ///  </ Summary> 
        ///  <Returns> </ Returns> 
        public Conduit Reverse ()
        {
            Conduit app = str =>
             {
                 str = " initialized! " ;
                  return Task.CompletedTask;
             };
            foreach (var component in _middlelist.Reverse())//倒序
            {
                app = component(app);
            }
            return app;

        }




        /*
           public RequestDelegate Build()
           {

            IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();

               RequestDelegate app = context =>
               {
                   // If we reach the end of the pipeline, but we have an endpoint, then something unexpected has happened.
                   // This could happen if user code sets an endpoint, but they forgot to add the UseEndpoint middleware.
                   var endpoint = context.GetEndpoint();
                   var endpointRequestDelegate = endpoint?.RequestDelegate;
                   if (endpointRequestDelegate != null)
                   {
                       was message =
                           $"The request reached the end of the pipeline without executing the endpoint: '{endpoint.DisplayName}'. " +
                           $"Please register the EndpointMiddleware using '{nameof(IApplicationBuilder)}.UseEndpoints(...)' if using " +
                           $"routing.";
                       throw new InvalidOperationException(message);
                   }

                   context.Response.StatusCode = 404;
                   return Task.CompletedTask;
               };

               foreach (var component in _components.Reverse())
               {
                   app = component(app);
               }
               return app;
           }
           */
    }
}

 running result:

 

 

 So far, imitate Core middleware execution has been completed, the junior partner interested, you can create a new test procedure, test, you will find a lot of different things oh
 

Guess you like

Origin www.cnblogs.com/Qintai/p/11827973.html