syn*_*tic 8 c# middleware .net-core asp.net-core
我在Startup.Configure()方法中直接遇到了几种编写简单中间件的方法:
// Syntax 1.
app.Use((context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
return next();
});
// Syntax 2.
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
await next();
});
// Syntax 3.
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
await next.Invoke();
});
// Syntax 4.
app.Use(next =>
{
return ctx =>
{
ctx.Response.Headers.Add("X-Content-Type-Options", "nosniff");
return next(ctx);
};
});
Run Code Online (Sandbox Code Playgroud)
它们都一样吗?
语法 1 和语法 2 在功能上是不同的。语法 1 不等待next()完成其Task. 语法 1 将一个普通的 lambda 函数传递给Use并返回Task而不等待它完成。语法2传递一个asynclambda函数是awaiting在Task返回之前。该await关键字告诉应用程序暂停执行,直到next()任务完成。在您的示例代码中,这可能不会导致功能差异,但有时等待 aTask完成可能会有所不同。
语法 2 和语法 3 在语法上不同,但在功能上相同。语法 2 只是语法 3 的用户友好版本。参见Func<T>() 与 Func<T>.Invoke()
语法 1 和语法 4 在语法上不同但功能相同。语法 1 只是语法 4 的用户友好包装。请参阅UseExtension.cs
// syntax 1,2,3 use this
public static IApplicationBuilder Use(
this IApplicationBuilder app,
Func<HttpContext, Func<Task>, Task> middleware)
{
// which calls into syntax4
return app.Use(next =>
{
return context =>
{
Func<Task> simpleNext = () => next(context);
return middleware(context, simpleNext);
};
});
}
Run Code Online (Sandbox Code Playgroud)
语法4的使用Use方法IApplicationBuilder
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
Run Code Online (Sandbox Code Playgroud)
语法1、2和3使用的是扩展方法,IApplicationBuilder该方法是语法4中先前方法的包装。
public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware)
{
return app.Use(next =>
{
return context =>
{
Func<Task> simpleNext = () => next(context);
return middleware(context, simpleNext);
};
});
}
Run Code Online (Sandbox Code Playgroud)
对于语法2和3,有没有区别next.Invoke()和next()。它们都编译为相同的方法。