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执行无法达到效果,还未找到原因
-

浙公网安备 33010602011771号