.net8:拦截器Interceptors

news/2025/2/22 9:25:29/文章来源:https://www.cnblogs.com/axzxs2001/p/18725216

  在C#12中,引入了拦截器,但一直是试验性的功能,所以自己初步看了一下,没有写文章,最近在看AOT时,发现Dapper.AOT已经用上了这个功能,觉得还是整理一下,分享出来吧,如果以后这个功能改变了,或移除了,请无视这篇文章。

  下面是微软官方文档的提示:

  拦截器是一项试验性功能,在 C# 12 的预览模式下提供。在将来的版本中,该功能可能会发生中断性变更或被删除。因此,不建议将其用于生产或已发布的应用程序。

  其实拦截器实现比较简单,就是定义一个扩展方法,替换掉别的方法,别的方法是通过InterceptsLocation来指定的,只要保证扩展方法和原方法签名一至即可。这里要注意一点,就是需要在项目中定义一下InterceptsLocationAttribute,代码如下:

using System.Runtime.CompilerServices;var myclass = new MyClass();
myclass.Print("测试");
myclass.Print("测试");public class MyClass
{public void Print(string s){Console.WriteLine($"MyClass.Print({s})");}
}
namespace Interceptors
{public static class MyClassIntercepts{[InterceptsLocation("C:\\MyFile\\Source\\Repos\\Asp.NetCoreExperiment\\Asp.NetCoreExperiment\\Interceptors\\InterceptorsDemo\\Program.cs", 5, 9)]public static void InterceptorPrint(this MyClass myclass, string s){Console.WriteLine($"ABC.AOT下 MyClass.InterceptorPrint 拦截 MyClass.Print方法,参数是:{s}");}}
}namespace System.Runtime.CompilerServices
{[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]public sealed class InterceptsLocationAttribute(string filePath, int line, int column) : Attribute{}
}

  如果想用拦截器,需要在项目文件(.csproj)中添加InterceptorsPreviewNamespaces,显示说明拦截器的信息。

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Interceptors</InterceptorsPreviewNamespaces></PropertyGroup>
</Project>

  本来拦载器相对简单,就是在编译时作替换即可,这种用法自然使我想起了C#源生成器。什么是源生成器?来看一下一个例子。

  首先是一个源生成器的项目TypeMessageGenerator,需要修改一下项目类型和引入Nuget包如下:

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>netstandard2.0</TargetFramework><LangVersion>12.0</LangVersion><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup><ItemGroup><PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4"><PrivateAssets>all</PrivateAssets><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference><PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" /></ItemGroup>
</Project>

  代码实现相对简单,本例就是生成项目中的一些类,类成员等信息,放在外部的一个文件中。

using Microsoft.CodeAnalysis;namespace TypeMessageGenerator
{[Generator]public class TypeMembersSourceGenerator : ISourceGenerator{public void Execute(GeneratorExecutionContext context){var mainMethod = context.Compilation.GetEntryPoint(context.CancellationToken);var path = "C:\\MyFile\\abc\\typemembers.txt";File.WriteAllText(path, "");          File.AppendAllText(path, context.Compilation.Assembly.Name + "\r\n");File.AppendAllText(path, "========================\r\n");foreach (var typename in context.Compilation.Assembly.TypeNames){File.AppendAllText(path, typename + "\r\n");try{var mytype = context.Compilation.Assembly.GetTypeByMetadataName(typename);if (mytype == null){mytype = context.Compilation.Assembly.GetTypeByMetadataName($"{context.Compilation.Assembly.Name}.{typename}");}if (mytype == null){continue;}foreach (var member in mytype.GetMembers()){try{File.AppendAllText(path, $"-- {member.Name} {member.Kind} \r\n");foreach (var location in member.Locations){try{File.AppendAllText(path, $"---- {location.GetLineSpan().StartLinePosition.Line},{location.GetLineSpan().EndLinePosition.Character} {location.GetLineSpan().Path}\r\n");}catch (Exception exc){File.AppendAllText(path, $"1   {exc.Message} \r\n");}}}catch (Exception exc){File.AppendAllText(path, $"2   {exc.Message} \r\n");}}}catch (Exception exc){File.AppendAllText(path, $"3   {exc.Message} \r\n");}}}public void Initialize(GeneratorInitializationContext context){}}
}

  怎么使用呢?这里定义了一个控制台项目,添加项目引用,选择上面的TypeMessageGenerator项目,并增加 OutputItemType="Analyzer" ReferenceOutputAssembly="false"这两个属性。

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles></PropertyGroup><ItemGroup><ProjectReference Include="..\TypeMessageGenerator\TypeMessageGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /></ItemGroup></Project>

  在控制台项目中添加一个Person.cs文件,内容如下:

namespace UserDemoTypeMessageGenerator
{public class Person{public int ID { get; set; }public int Name { get; set; }public void PrintPerson(){}}
}

  在Program.cs中不用动,这时只需要生成项目,就会发现在C:\\MyFile\\abc下生成了typemembers.txt,具体内空如下:

UserDemoTypeMessageGenerator
========================
Program
-- <Main>$ Method 
---- 0,0 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Program.cs
-- .ctor Method 
---- 0,7 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Program.cs
Person
-- <ID>k__BackingField Field 
---- 4,21 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- ID Property 
---- 4,21 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- get_ID Method 
---- 4,27 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- set_ID Method 
---- 4,32 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- <Name>k__BackingField Field 
---- 6,23 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- Name Property 
---- 6,23 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- get_Name Method 
---- 6,29 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- set_Name Method 
---- 6,34 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- PrintPerson Method 
---- 8,31 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs
-- .ctor Method 
---- 2,23 C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\SourceGenerator\UserDemoTypeMessageGenerator\Person.cs

  这时要他细看,生成的这个Txt中----后,两个数字,一个路径,是不是和拦截器一样,这时你有没有一些想法?

  文章来源微信公众号

  想要更快更方便的了解相关知识,可以关注微信公众号 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/886887.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于电压矢量变换的锁相环simulink建模与仿真

1.课题概述 基于电压矢量变换的锁相环simulink建模与仿真,这个模型的基本构架如下所示:2.系统仿真结果由图中锁相结果可以看出,利用新型锁相环技术在电网电压平衡条件和不平衡条件下均可对基波正序电压分量实现快速准确的锁相输出。这将在后面研究系统 电压不平衡环境下负序…

Spatial Data Analysis简易教程

1. 因子的多重共线性 (1)Perason相关系数(不推荐) SPSS-分析-》相关-》双变量-》确定,选择相关系数较小的因子:但是在分析-》回归-》线性中共线性诊断中,仍有3个变量的VIF>10,因此,该方法不可取。(2)共线性诊断 分析-》回归-》线性,在选项中勾选共线性诊断,方法…

基于线性核函数的SVM数据分类算法matlab仿真

1.程序功能描述 基于线性核函数的SVM数据分类算法matlab仿真,通过程序产生随机的二维数据,然后通过SVM对数据进行分类,SVM通过编程实现,不使用MATLAB自带的工具箱函数。 2.测试软件版本以及运行结果展示MATLAB2022A版本运行 (完整程序运行后无水印) 3.核心程序 % …

服务器 压测cpu

一. 使用的工具 1. taskset简单理解为: -c 找 cpu核心 -p 找 已存在进程2. stress 二 . 查看cpu核心个数 ,命令 lscpu 三. 使用taskset 与 yes 命令简单测试,htop查看cpu使用率 1. 测试第一个cpu核心 taskset -c 0 yes >> 1.txt 2. 测试第二个cpu核心taskset -c 1 y…

宽字节注入 sqli-lab lesson 32

1.判断注入 1.输入 1,addslashes函数将 进行转义变为 \ ,此时的单引号仅作为普通的字符2.输入1%df,addslashes 函数将 进行转义变为 \ ,此时 %df%5c会进行结合变成了一个汉字 運,因此SQL查询语句成功被改变了从而引起了报错 1%df =>1%df%5c3.将多余的进行注释然后按照…

Hume AI 即将推出新 AI 语音产品;声网上线对话式 AI 引擎,15 分钟让 DeepSeek 开口说话丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…

DDPM

前向过程 扩散模型的前向过程指的是向原始数据中逐渐添加高斯噪声直到数据完全变成噪声的过程。假设\(q(x_0)\)是真实图像的分布,通过从训练集的真实图像中随机采样一张图像,表示\(x \sim q(x_0)\)。那么前向过程\(q(x_t | x_{t-1})\)指的是在前向的每一步中通过对图像\(x_{t…

同事PPT又拿奖了?偷偷用这AI工具,3步做出老板狂赞的年度报告

大家好,我是六哥,今天为大家分享一款PPT辅助神器,年底汇报必备神器!就是Napkin AI ! 这是一款超级酷的工具,它能把你写的文字一秒钟转化为各种炫酷的视觉效果,比如图表、流程图、信息图啥的。如果你想做一个引人注目的演示,或者想让你的博客文章更有吸引力,Napkin简直…

1.Java入门

本章目标简介 计算机基础 计算机语言发展史 java语言 JDK安装 第一个HelloWorld 集成开发环境本章内容 一、简介 1、企业用人的标准 我们在说人的能力的时候通常是有这三种说法:人的专业知识能力 人的执行能力 人学习的能力。在这三种能力当中,其实最重要的反而学习能力。你可…

洛谷P1990 覆盖墙壁 题解

洛谷P1990 覆盖墙壁 题解 题目传送门。 本题是一道非常好的递推题,请认真阅读,争取不看代码自己写出答案。 思路 我们可以设 \(f_i\) 为覆盖 \(2\times i\) 的所有覆盖方案。显然,边界条件 \(f_0\)(即没有列了,不用覆盖)和 \(f_1\)(只有 1 列,即一个 \(\text I\) 型砖块…

Spring复习--后处理器、生命周期

Spring实例化的基本流程 将xml中的bean标签封装到一个BeanDefinition对象中,然后将BeanDefinition对象存储到一个BeanDefinitionMap<String,BeanDefinition>集合中去,通过对BeanDefinitionMap进行遍历,使用反射创建bean示例对象存储到singletonObjects<String,Obje…

Profinet转EtherNet/IP:驱动西门子1500与罗克韦尔PLC高效通讯

Profinet转EtherNet/IP:驱动西门子1500与罗克韦尔PLC高效通讯一、项目背景在某大型自动化生产车间内,生产架构呈现多元化。一部分生产线基于罗克韦尔自动化(AB)体系搭建,核心控制由AB的PLC承担;与此同时,车间新添了采用西门子S7-1500 PLC控制的设备。 为确保整个车间生产…