直接通过反射 找到类
RequestDelegate 和 InvokeAsync 这2个都是固定写法 框架帮我们写死的 ,
如果看是不是中间件,框架先检查 参数 有没有InvokeAsync方法和第一个参数必须是RequestDelegate
源码如下 :
app.UseMiddleware<OnetMiddleWare>();
public class OneMiddleWare { private readonly RequestDelegate _next; public OneMiddleWare(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { await context.Response.WriteAsync($"{nameof(OneMiddleWare)},Hello World1!<br/>"); await _next(context); await context.Response.WriteAsync($"{nameof(OneMiddleWare)},Hello World2!<br/>"); } }
app.UseMiddleware<TwoMiddleWare>(); 是实现 IMiddleware 接口 TwoMiddleWare类型的初始化是请求来了之后才发生, 实现IMiddleware,就不能有参数--而且还得IOC注册
public class TwoMiddleWare : IMiddleware, IDisposable { private readonly ILogger _logger; public TwoMiddleWare(ILogger<TwoMiddleWare> logger) { this._logger = logger; } public async Task InvokeAsync(HttpContext context, RequestDelegate next) { this._logger.LogWarning($"{nameof(TwoMiddleWare)},Hello World1!<br/>"); await context.Response.WriteAsync($"{nameof(TwoMiddleWare)},Hello World1!<br/>"); await next(context); await context.Response.WriteAsync($"{nameof(TwoMiddleWare)},Hello World2!<br/>"); } public void Dispose() { Console.WriteLine("释放需要释放的资源"); } }
app.UseMiddleware<ThreeMiddleWare>("tet"); 可以带参数 前面第一个参数 和第三个参数不是ioc 注入的 是传入的
,而第二个参数是ioc 生成的。我们没有service 里面 添加ThreeMiddleWare 的注册
public class ThreeMiddleWare { private readonly RequestDelegate _next; private readonly ILogger _logger; private readonly string _Message; public ThreeMiddleWare(RequestDelegate next, ILogger<ThreeMiddleWare> logger, string message) { this._next = next; this._logger = logger; this._Message = message; } /// <summary> /// 1 方法名字Invoke或者InvokeAsync /// 2 返回类型必须是Task /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task Invoke(HttpContext context) { Console.WriteLine($"{nameof(ThreeMiddleWare)}---{this._Message}"); if (!context.Request.Path.Value.Contains("jason")) { await context.Response.WriteAsync($"{nameof(ThreeMiddleWare)}This is End<br/>"); } else { await context.Response.WriteAsync($"{nameof(ThreeMiddleWare)},Hello World ThreeMiddleWare!<br/>"); await _next(context); await context.Response.WriteAsync($"{nameof(ThreeMiddleWare)},Hello World ThreeMiddleWare!<br/>"); } } }
在bulid 的时候 才执行里面的 委托方法 。
结论 one 和three 都是在bulid 的时候 已经初始化好中间件了 已经通过反射创建好了,而通过接口的twomiddleware 是请求来的时候,实例化这个类的,2者还是有区别,如果想做资源的释放可以用第二种接口形式的。相应时候实例化,用过gc掉,如果用接口的形式还要注册一下 services.AddSingleton<TwoMiddleWare>(); 第一第三种是通过反射创建对象的,第二种是ioc 所以这就解释了为什么要在ConfigureServices 注册一下。