Source Generator初探
Posted 摧残一生 涅槃重生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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执行无法达到效果,还未找到原因
-
以上是关于Source Generator初探的主要内容,如果未能解决你的问题,请参考以下文章