摘要:最近刚好在看roslyn/native aot相关的内容,看到rdg的实现时,发现拦截器有了一次更新仅以此作为记录
最近刚好在看roslyn/native aot相关的内容,看到rdg的实现时,发现拦截器有了一次更新仅以此作为记录
拦截器是一种方法,该方法可以在编译时以声明方式将对可拦截方法的调用替换为对其自身的调用。通过让拦截器声明所拦截调用的源位置,可以进行这种替换。拦截器可以向编译中(例如在源生成器中)添加新代码,从而提供更改现有代码语义的有限能力。
https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-12#interceptors
根据roslyn docs/features/interceptors.md 的说法,在.NET 9.0.2xx SDK之后已经获得了"稳定"的支持
Interceptor 拦截器作为c# 12的预览功能加入,net8中用户必须启用
InterceptorsPreview并且自己定义一个 InterceptsLocationAttribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]file sealed class InterceptsLocationAttribute(string filePath, int line, int character) : AttributeInterceptsLocation构造函数需要
被替换方法完整路径
被替换方法所处行
被替换方法调用位置
因为InterceptsLocation特性要包含完整的文件名及位置引起大量讨论最终微软修改了定义
启用方式变更为设定需要启用的命名空间(只需要指定替换方法所处的命名空间 这部分在rc2中已经修改)
$(InterceptorsPreviewNamespaces)自定义特性变为
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]file sealed class InterceptsLocationAttribute(int version, string data) : Attribute新版的InterceptsLocation构造函数只接受version和data 根据相关文档得知 version为编码器版本号 当前只有1
data的编码方式为
被替换方法所处文件内容哈希校验和(16 byte )
被替换方法调用位置(int32)
被替换方法所处文件名(utf-8 string )
修改之后实际基本上可以确定必须要和源代码生成器绑定使用
data值的计算rolsyn的语义模型已经提供了计算方式但仍处于评估状态
想体验一下可以自己实现
自己实现一个替换默认console输出的源代码生成器产生的代码如下
实际执行情况如下
反编译可以看到方法调用已经被修改
来源:opendotnet