问题
如果需要在C#项目中自定义中间件,该如何实现呢?
前置条件
- 基于
.Net 6.0创建的C#Demo - 主要目录结构如下
DemoApplication
|---> src
|---> controller folder
|---> service folder
|---> Program.cs
|---> Middleware.cs
中间件
C#项目中有两种类型的中间件,一种是系统提供的默认的中间件,一种是用户自定义的中间件。中间件作用于入口程序到Controller层之间,如下图所示:
flowchart LR
A0[Program.cs] --> |config| M0[default Middleware]
A0[Program.cs] --> |config| M1[custom Middleware]
M0 --> A[Controller]
M1 --> A
自定义中间件
自定义中间件Middleware.cs,在构造函数中传入RequestDelegate对象,然后实现InvokeAsync方法,在方法实现具体的逻辑。最后将context传递下去。
// Middleware.cs
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
// system defined InvokeAsync
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine("This is Custom Middleware...");
doSomething();
await _next(context);
}
}
在Program.cs文件中引用自定义的中间件CustomMiddleware
// Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// 配置中间件
app.UseMiddleware<CustomMiddleware>();
在中间件中调用Service层的方法
在中间件中可以使用IServiceScopeFactory来调用Service层的方法。在构造函数中以参数的方式传入IServiceScopeFactory,然后在具体的方法中通过_serviceScopeFactory.CreateScope().ServiceProvider.GetRequiredService来调用具体的service服务。
示例如下:
// Middleware.cs
public class CustomMiddleware
{
private readonly RequestDelegate _next;
private readonly IServiceScopeFactory _serviceScopeFactory;
public CustomMiddleware(RequestDelegate next, IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
// 这里
using var scope = _serviceScopeFactory.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<ICustomService>();
service.method();
await _next(context);
}
}