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 实际执行方法,最好的使用场景是定制化开发,比如客户需求和产品实现完全不同,可以保证请求不变的情况下执行客户定制化实现。

本文作者:My IO信息来源:公众号 My IO所属分类:.NET

ASP.NET Core替换Action实际执行方法的更多相关文章

  1. 《ASP.NET Core In Action》读书笔记系列一 ASP.NET Core 的诞生

    最近打算系统学习一下asp.net  core ,苦于没有好的中文书藉,只好找来一本英文的 <ASP.NET Core In Action>学习.我和多数人一样,学习英文会明显慢于中文.希 ...

  2. 《ASP.NET Core In Action》读书笔记系列,这是一个手把手的从零开始的教学系列目录

    最近打算系统学习一下asp.net  core ,苦于没有好的中文书藉,只好找来一本英文的 <ASP.NET Core In Action>学习.我和多数人一样,学习英文会明显慢于中文.希 ...

  3. 第12章 使用 Entity Framework Core 保存数据(ASP.NET Core in Action, 2nd Edition)

    本章包括(请点击这里阅读其他章节) 什么是实体框架核心以及为什么应该使用它 向 ASP.NET Core 应用程序添加实体框架核心 构建数据模型并使用它创建数据库 使用实体框架核心查询.创建和更新数据 ...

  4. 第10章 带有依赖注入的服务配置(ASP.NET Core in Action, 2nd Edition)

    第2部分 构建完整的应用程序 我们在第一部分中讨论了很多内容.您看到了ASP.NET Core应用程序是如何由中间件组成的,我们主要关注RazorPages框架.您了解了如何使用Razor语法构建传统 ...

  5. 第9章 使用MVC为移动和客户端应用程序创建Web API(ASP.NET Core in Action, 2nd Edition)

    本章包括 创建Web API控制器以向客户端返回JSON 使用属性路由自定义URL 使用内容协商生成响应 使用[ApiController]属性应用通用约定 在前五章中,您已经完成了服务器端渲染ASP ...

  6. 第8章 使用标记帮助工具构建表单(ASP.NET Core in Action, 2nd Edition)

    本章包括 使用Tag Helpers轻松构建表单 使用锚标记帮助程序生成URL 使用Tag Helpers为Razor添加功能 在第7章中,您了解了Razor模板以及如何使用它们为应用程序生成视图.通 ...

  7. asp.net core 动态更新 appsetting.json方法

    如何将值更新到appsetting.json? 我正在使用官方文档中IOptions描述的模式. 当我从中读取值时appsetting.json,这可以正常工作,但是如何更新值并将更改保存回来apps ...

  8. 第17章 使用日志记录监视和排除错误(ASP.NET Core in Action, 2nd Edition)

    第3部分 扩展应用程序 我们在第1部分和第2部分中介绍了大量内容:我们查看了您将用于构建传统服务器渲染的 Razor Pages 应用程序以及 Web API 的所有主要功能组件.在第3部分中,我们将 ...

  9. 第15章 授权:保护您的应用程序(ASP.NET Core in Action, 2nd Edition)

    本章包括 使用授权控制谁可以使用你的应用 对策略使用基于声明的授权 创建自定义策略以处理复杂的需求 根据所访问的资源授权请求 隐藏用户未经授权访问的Razor模板中的元素 在第14章中,我向您展示了如 ...

  10. 第14章 身份验证:使用Identity将用户添加到应用程序(ASP.NET Core in Action, 2nd Edition)

    本章包括 ASP.NET Core中web应用程序的身份验证工作原理 使用ASP.NET Core标识系统创建项目 向现有web应用添加用户功能 自定义默认ASP.NET Core标识UI 像ASPN ...

随机推荐

  1. mask2former出来的灰度图转切割轮廓后的二值图

    切割后的灰度图 转成二值图代码如下 点击查看代码 # This is a sample Python script. import cv2 import numpy as np # Press Shi ...

  2. 深入解析C++的auto自动类型推导

    关键字auto在C++98中的语义是定义一个自动生命周期的变量,但因为定义的变量默认就是自动变量,因此这个关键字几乎没有人使用.于是C++标准委员会在C++11标准中改变了auto关键字的语义,使它变 ...

  3. 堆结构(Heap)的基本实现【数据结构与算法—TypeScript 实现】

    笔记整理自 coderwhy 『TypeScript 高阶数据结构与算法』课程 概念 本质:一种特殊的树结构,由 完全二叉树 实现 多数情况为二叉堆 二叉堆:最大堆.最小堆 最大堆:堆上的每个节点都的 ...

  4. HarmonyOS SDK 助力新浪新闻打造精致易用的新闻应用

    原生智能是HarmonyOS NEXT的核心亮点之一,依托HarmonyOS SDK丰富全面的开放能力,开发者只需通过几行代码,即可快速实现AI功能.新浪新闻作为鸿蒙原生应用开发的先行者之一,从有声资 ...

  5. 第十三篇:HTML和CSS入门

    一.HTML本质以及在WEB程序中的作用 1.一套规则,浏览器认识的规则. 2.开发者: 学习html规则 开发后台程序 - 写html文件(充当模板的作用) - 数据库获取数据,然后替换到html文 ...

  6. mac版本vscode窗口崩溃crashed

    1.截图 出现时机 当安装依赖的时候大概率会出现,甚至安装一次依赖会出现几次 解决 具体原因未知 重新启动电脑以及退出软件都不能解决 去官网重新下载,重新安装问题解决

  7. eclipse 汉化语言包/中文补丁/简中设置/中英互换

    eclipse 汉化语言包/中文补丁/简中设置/中英互换 汉化很简单,使用eclipse内置的软件下载就可以,不需要下载压缩包 官方的说明 Open the install wizard with ' ...

  8. 牛客网-SQL专项训练14

    ①通过子查询的方式从衬衫表SHIRTABLE中选取出销售单价shirt_price高于全部衬衫的平均价格的衬衫名字:B 解析: 题目要求需要用到子查询,故排除AC选项,而D选项在where子句中使用了 ...

  9. HarmonyOS NEXT应用开发—在Native侧实现进度通知功能

    介绍 本示例通过模拟下载场景介绍如何将Native的进度信息实时同步到ArkTS侧. 效果图预览 使用说明 点击"Start Download"按钮后,Native侧启动子线程模拟 ...

  10. 提质增效,安全灵活,阿里云EDA上云方案让芯片设计驶入高速路

    简介: 今天下午14点,直播间等你 导语:随着芯片工艺的跃升,EDA 需要越来越大的计算能力,处理高达PB级的海量数据.传统的算力交付模式已无法跟上快速发展的芯片设计行业,云的快速交付与强大生态提供了 ...