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