Source Generator初探(一)
Source Generator
什么是Source Generator
.NET 5引入的系特性,可在应用编译期间根据当前编译信息动态生成代码,也可以直接引用动态生成的代码。
优势
加快运行速度
原有的程序机制是初次运行时通过反射进行依赖注入,这时会导致第一次运行加载大量数据,运行会慢,再一个不利于AOT编译。
而Source Generator是在编译时完成依赖注入,把之前运行所作的大部分工作都完成,这样即可利于AOT编译,又可以保证运行时的速度。
增加了代码的灵活性
将运行时加载变为了编译时加载,可以让程序在编译时动态加载程序员想要的代码,这些代码可以来源于Xml,JSON等文件,依次类推,我们可以通过维护Xml或者JSON来动态编译实现无代码平台。
解决AOT编译
AOT也是一个新特性,但使用反射的程序无法使用该特性,使用Source Generator可避免AOT特性无法使用的情况。
第一个Source Generator例子
-
创建一个控制台程序
-
选择控制台应用,下一步
-
创建项目名称,下一步
-
框架选择默认(目前默认的为Net 6.0),并勾选不适用顶级语句,创建项目
-
修改Program.cs代码,修改部分如下:
namespace SourceGeneratorDemo { // internal 改为 partial,否则可见级别太低,使用public的话Program可见级别太高 partial class Program { static void Main(string[] args) { Console.WriteLine("Hello, World!"); // 添加该行 HelloCode("Hello, Code"); } // 添加该行 动态编译并调用HelloCode static partial void HelloCode(string name); } }
-
此时,直接编译并运行可通过,HelloCode方法未找到会自动跳过
-
-
创建netstandard2.0的类库项目
-
选择类库项目,下一步
-
添加项目名称,下一步
-
选择框架(netstandard2.0),创建
-
添加Microsoft.CodeAnalysis.Analyzers 和 Microsoft.CodeAnalysis.CSharp依赖,依赖项信息可通过点击项目进行查看
<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.5.0" /> </ItemGroup>
-
将Class1.cs改名为SourceGeneratorMethod.cs,并添加代码
[Generator] public class HelloSourceGenerator : ISourceGenerator { public void Execute(GeneratorExecutionContext context) { // Find the main method var mainMethod = context.Compilation.GetEntryPoint(context.CancellationToken); // Build up the source code string source = $@"// <auto-generated/> using System; namespace {mainMethod.ContainingNamespace.ToDisplayString()} {{ public static partial class {mainMethod.ContainingType.Name} {{ static partial void HelloCode(string name) => Console.WriteLine($""Generator says: Hi from '{{name}}'""); }} }} "; var typeName = mainMethod.ContainingType.Name; // Add the source code to the compilation context.AddSource($"{typeName}.g.cs", source); } public void Initialize(GeneratorInitializationContext context) { // No initialization required for this one } }
-
编译SourceGenerator项目
-
-
在控制台中添加对类库的依赖
-
SourceGeneratorDemo项目中选择依赖项,点击右键添加项目引用,引用类库项目
-
双击SourceGeneratorDemo项目,添加
OutputItemType
和ReferenceOutputAssembly
属性<ItemGroup> <ProjectReference Include="..\SourceGenerator\SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup>
-
生成SourceGeneratorDemo并运行
-
结果,并没有输出Hello, Code
-
-
问题解决
-
重新打开项目
-
将Microsoft.CodeAnalysis.Analyzers 和 Microsoft.CodeAnalysis.CSharp引用修改为如下引用:
<ItemGroup> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" /> <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup>
-
清理SourceGenerator和SourceGeneratorDemo项目
-
重新运行,出现了Hello,Code
-
-
原因判断:
-
经测试,Microsoft.CodeAnalysis.Analyzers可不使用,只需要引用Microsoft.CodeAnalysis.CSharp即可
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
-
Microsoft.CodeAnalysis.CSharp的4.5.0版本和4.6.0-1.final执行无法达到效果,还未找到原因
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?