北航刘禹导师做网站,桂林网站制作公司华彩,网站已运行时间代码,优化器RequestDelegate上次#xff0c;我们在《如何判断当前请求的API类型》中查看endpoints.MapControllers()实现时#xff0c;最终定位到ActionEndpointFactory.cs#xff0c;其中有这样一段代码#xff1a;private static RequestDelegate CreateRequestDelegate()
{// We do… RequestDelegate上次我们在《如何判断当前请求的API类型》中查看endpoints.MapControllers()实现时最终定位到ActionEndpointFactory.cs其中有这样一段代码private static RequestDelegate CreateRequestDelegate()
{// We dont want to close over the Invoker Factory in ActionEndpointFactory as// that creates cycles in DI. Since were creating this delegate at startup time// we dont 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.GetMetadataIDataTokensMetadata();var routeData new RouteData();routeData.PushState(router: null, context.Request.RouteValues, new RouteValueDictionary(dataTokens?.DataTokens));// Dont close over the ActionDescriptor, thats not valid for pages.var action endpoint.Metadata.GetMetadataActionDescriptor()!;var actionContext new ActionContext(context, routeData, action);if (invokerFactory null){invokerFactory context.RequestServices.GetRequiredServiceIActionInvokerFactory();}var invoker invokerFactory.CreateInvoker(actionContext);return invoker!.InvokeAsync();};
}从代码上理解应该是执行请求时会创建IActionInvokerFactory实例由它创建 invoker 执行。是不是这样呢我们验证一下IActionInvokerFactory新建CustomActionInvokerFactory.cs继承IActionInvokerFactory实现代码如下public class CustomActionInvokerFactory : IActionInvokerFactory
{private readonly IActionInvokerProvider[] _actionInvokerProviders;public ActionInvokerFactory(IEnumerableIActionInvokerProvider 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.AddSingletonIActionInvokerFactory, CustomActionInvokerFactory();...
}打上断点执行API发现确实如设想中一样请求时执行CreateInvoker方法在其中发现了一个很有意思的属性MethodInfo,正是对应我们执行的 Action 方法。突发奇想如果我们替换MethodInfo属性是不是会执行其他方法呢Demo创建 WeatherForecast2Controller实现代码如下[ApiController]
[Route([controller])]
public class WeatherForecast2Controller : ControllerBase
{[HttpGet]public string Get2(){return My IO;}
}可以看到这是和原方法完全不同的实现。现在进行替换var actionDescriptor actionContext.ActionDescriptor as ControllerActionDescriptor;
actionDescriptor.MethodInfo typeof(WeatherForecast2Controller).GetMethod(Get2);执行出现错误提示查看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 实际执行方法最好的使用场景是定制化开发比如客户需求和产品实现完全不同可以保证请求不变的情况下执行客户定制化实现。想了解更多内容请关注我的个人公众号”My IO“