nem*_*mui 12 c# asp.net-web-api asp.net-core
我查看了MapGet()正在执行的操作,发现其中一个重载采用类型Delegate(类,不是关键字,也不是RequestDelegate),但随后将其传递给MapMethods(),后者采用RequestDelegate. 我觉得非常令人困惑的是这个演员阵容是如何发生的。ARequestDelegate有签名delegate Task RequestDelegate(HttpContext httpContext)。当将一个委托转换为另一个委托时,他们不是a)需要相同的签名,b)实际上需要传递对Invoke()委托方法的引用(也就是说,你不能只将一个委托转换为另一个委托,而不管它们的签名)匹配,或者我是这么读的)。
我发现极其令人困惑的另一件事是如何将任意请求处理程序传递给 Minimal API,并以某种方式将其转换为RequestDelegate. Microsoft 的文档显示了处理程序没有诸如 之类的参数的示例() => ...,以及将通过诸如 之类的依赖注入机制解析的任意参数(MyClass a, HttpContext ctx, DbContext<MyClass> dbCtx) => ...。我假设这个处理程序以某种方式包装在另一个适合签名的 lambda 中RequestDelegate,以便 ASP.NET Core 可以传入 a HttpContext,然后包装 lambda 可以分析开发人员传入的 lambda 并决定如何解决其依赖关系等。但我完全不知道这是在哪里或如何发生的。它实际上只是接受一个 Delegate 并将其传递给另一个接受 的方法RequestDelegate,神奇的是它现在是一个有效的RequestDelegate?
有谁知道?
dav*_*owl 23
首先,没有魔法。这些路由方法有 2 组不同的重载。RequestDelegate自 .NET Core 3.1 以来就一直存在的方法,以及采用Delegate. 对于问题的前半部分,无法任意投射,Delegate但RequestDelegate另一种方法确实有效。我不确定您正在阅读什么代码,但如果您链接到它将会有所帮助:)。
至于第二部分,这基本上就是最小 API 的工作原理。我们将任意值转换Delegate为RequestDelegate. 该过程很复杂,并在运行时根据Delegate传入的参数和返回值生成代码。神奇的事情发生在RequestDelegateFactory中。输入是 a Delegate,输出是 a RequestDelegate。返回RequestDelegate的 遵循这些参数绑定规则以及如何解释返回值。
在幕后,我们使用动态代码生成来创建RequestDelegate. 一种简单的思考方法是,我们生成您手动编写的代码,以从传入请求中读取数据,然后使用这些数据调用您的函数。这是一个例子:
app.MapGet("/hello", (string? name) => $"Hello {name ?? "World"}");
Run Code Online (Sandbox Code Playgroud)
在此情况下将变成:
app.MapGet("/hello", (HttpContext context) =>
{
string name = context.Request.Query["name"];
// handler is the original delegate
string result = handler(name);
return context.Response.WriteAsync(result);
});
Run Code Online (Sandbox Code Playgroud)
展示一个稍微复杂一点的例子:
app.MapPost("/api/products", (Product p) =>
{
...
return Results.Ok(p);
});
Run Code Online (Sandbox Code Playgroud)
变成:
app.MapPost("/api/products", async (HttpContext context) =>
{
var product = await context.Request.ReadFromJsonAsync<Product>();
if (product is null)
{
context.Response.StatusCode = 400;
return;
}
var result = handler(product);
await result.ExecuteAsync(context);
});
Run Code Online (Sandbox Code Playgroud)
这个翻译被封装在中,RequestDelegateFactory所以你甚至可以做这样的事情:
app.Use(next =>
{
RequestDelegateResult result = RequestDelegateFactory.Create(() => "Hello World");
return result.RequestDelegate;
});
Run Code Online (Sandbox Code Playgroud)
该中间件会将 hello world 写入生成的响应RequestDelegate,并将遵循与最小 API 相同的规则,但没有路由部分。
希望这能解释一些“魔法”。
| 归档时间: |
|
| 查看次数: |
3927 次 |
| 最近记录: |