RequestDelegate
上次,我们在《如何判断当前请求的API类型》中查看endpoints.MapControllers()
实现时,最终定位到ActionEndpointFactory.cs,其中有这样一段代码:
private static RequestDelegate CreateRequestDelegate()
{
// We don't want to close over the Invoker Factory in ActionEndpointFactory as
// that creates cycles in DI. Since we're creating this delegate at startup time
// we don't want to create all of the things we use at runtime until the action
// actually matches.
//
// The request delegate is already a closure here because we close over
// the action descriptor.
IActionInvokerFactory? invokerFactory = null;
return (context) =>
{
var endpoint = context.GetEndpoint()!;
var dataTokens = endpoint.Metadata.GetMetadata<IDataTokensMetadata>();
var routeData = new RouteData();
routeData.PushState(router: null, context.Request.RouteValues, new RouteValueDictionary(dataTokens?.DataTokens));
// Don't close over the ActionDescriptor, that's not valid for pages.
var action = endpoint.Metadata.GetMetadata<ActionDescriptor>()!;
var actionContext = new ActionContext(context, routeData, action);
if (invokerFactory == null)
{
invokerFactory = context.RequestServices.GetRequiredService<IActionInvokerFactory>();
}
var invoker = invokerFactory.CreateInvoker(actionContext);
return invoker!.InvokeAsync();
};
}
从代码上理解,应该是执行请求时,会创建IActionInvokerFactory
实例,由它创建 invoker 执行。
是不是这样呢,我们验证一下!
IActionInvokerFactory
新建CustomActionInvokerFactory.cs
,继承IActionInvokerFactory,实现代码如下:
public class CustomActionInvokerFactory : IActionInvokerFactory
{
private readonly IActionInvokerProvider[] _actionInvokerProviders;
public ActionInvokerFactory(IEnumerable<IActionInvokerProvider> actionInvokerProviders)
{
_actionInvokerProviders = actionInvokerProviders.OrderBy(item => item.Order).ToArray();
}
public IActionInvoker? CreateInvoker(ActionContext actionContext)
{
var context = new ActionInvokerProviderContext(actionContext);
foreach (var provider in _actionInvokerProviders)
{
provider.OnProvidersExecuting(context);
}
for (var i = _actionInvokerProviders.Length - 1; i >= 0; i--)
{
_actionInvokerProviders[i].OnProvidersExecuted(context);
}
return context.Result;
}
}
代码 Copy 自 ASP.NET Core 内部实现类ActionInvokerFactory。
然后在 Startup.cs 注册实现:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IActionInvokerFactory, CustomActionInvokerFactory>();
...
}
打上断点,执行API,发现确实如设想中一样,请求时执行CreateInvoker
方法:
查看ControllerActionInvokerCache.cs
实现:
var objectMethodExecutor = ObjectMethodExecutor.Create(
actionDescriptor.MethodInfo,
actionDescriptor.ControllerTypeInfo,
parameterDefaultValues);
原来,还要替换actionDescriptor.ControllerTypeInfo
:
var actionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor;
actionDescriptor.MethodInfo = typeof(WeatherForecast2Controller).GetMethod("Get2");
actionDescriptor.ControllerTypeInfo = typeof(WeatherForecast2Controller).GetTypeInfo();
再次运行,执行成功!
结论
替换 Action 实际执行方法,最好的使用场景是定制化开发,比如客户需求和产品实现完全不同,可以保证请求不变的情况下执行客户定制化实现。
本博客Android APP 下载 |
![]() |
支持我们就给我们点打赏 |
![]() |
支付宝打赏 支付宝扫一扫二维码 |
![]() |
微信打赏 微信扫一扫二维码 |
![]() |
如果想下次快速找到我,记得点下面的关注哦!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!