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. CabloyJS 4.22重磅推出弹出式页面交互风格

    升级说明 我们知道CabloyJS提供了pc=mobile+pad自适应布局机制,可以通过一套代码同时适配mobile端和pc端.基本思路就是优先适配mobile端,然后再把mobile端的交互体验带 ...

  2. HarmonyOS后台任务管理开发指南上线!

      为什么要使用后台任务?开发过程中如何选择合适的后台任务?后台任务申请时存在哪些约束与限制? 针对开发者使用后台任务中的疑问,我们上线了概念更明确.逻辑结构更清晰的后台任务开发指南,包含具体的使用场 ...

  3. Weblogic、Tomcat、Apache、Nginx等web容器学习笔记

    1.weblogic weblogic是美国Oracle公司的一款产品,是一个基于JAVAEE架构的中间件.是用于开发.集成.部署 .管理大型分布式Web应用.网络应用.数据库应用的Java应用服务器 ...

  4. 这些Git事故灾难, 你经历过几个?

    前言 关于Git, 相信大家最常用的就是pull和push. 但随着协作规模的提升, 遇到的问题也会越来越多. 本篇文章并不科普一些命令的详细用法, 更多的是分享在工作中遇到的Git场景问题以及踩过的 ...

  5. flask通过线程池实现异步

    from flask import Flask from time import sleep from concurrent.futures import ThreadPoolExecutor # D ...

  6. Spring 源码阅读(一)环境搭建

    注意事项: 使用 2024-03-14 发布的 Spring 5.3.33 版本 IDE 工具使用了 Intellij IDEA,同时为了简化不必要的内容没单独配置 Gradle 环境 JDK 版本采 ...

  7. 力扣1045(MySQL)-买下所有产品的客户(中等)

    题目: Customer 表: Product 表: 写一条 SQL 查询语句,从 Customer 表中查询购买了 Product 表中所有产品的客户的 id. 示例:  解题思路: 建表语句: 1 ...

  8. EMR StarRocks 极速数据湖分析原理解析

    简介:数据湖概念日益火热,本文由阿里云开源大数据 OLAP 团队和 StarRocks 数据湖分析团队共同为大家介绍" StarRocks 极速数据湖分析 "背后的原理. [首月9 ...

  9. 如何进行基于Anolis OS的企业级Java应用规模化实践?|龙蜥技术

    ​简介:提供了7×24小时的专属钉钉或者电话支持,响应时间保证到在业务不可用情况下10分钟响应,业务一般的问题在一小时可以获得响应,主要城市可以两小时内得到到达现场的服务. 本文作者郁磊,是Java语 ...

  10. dotnet 推荐一个使用 Json 直接路由通讯的 IPC 库

    本文将和大家推荐一个我所在团队开源的本机多进程通讯 IPC 库,此 IPC 支持使用 JSON 格式进行直接路由通讯,具有使用方便,稳定性高,性能好的优点 这是我所在的团队在 GitHub 上使用最友 ...