内容目录
Create a new project that only uses netstandard2. The complete content of its csproj file is as follows:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
</ItemGroup>
</Project>
Then create a type that implements ISourceGenerator.
[Generator]
public class AOPSourceGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
}
public void Execute(GeneratorExecutionContext context)
{
Debugger.Launch();
SyntaxTree syntaxTree = context.Compilation.SyntaxTrees.FirstOrDefault();
if (syntaxTree != null)
{
var root = syntaxTree.GetCompilationUnitRoot();
var rewriter = new AOPRewriter();
var newRoot = rewriter.Visit(root);
// Add generated file to compilation; the file is temporary
context.AddSource("AAA.cs", newRoot.GetText());
var updatedDoc = syntaxTree.WithChangedText(newRoot.GetText());
// Persist the file
using (var fileStream = new FileStream("BBB.cs", FileMode.Truncate))
{
updatedDoc.GetTextAsync().Result.Write(new StreamWriter(fileStream));
}
}
}
// Responsible for modifying code
class AOPRewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitBinaryExpression(BinaryExpressionSyntax node)
{
if (node.OperatorToken.IsKind(SyntaxKind.AsteriskToken))
{
// Replace x * x with x + x
var newNode = node.WithOperatorToken(SyntaxFactory.Token(SyntaxKind.PlusToken));
return newNode;
}
return base.VisitBinaryExpression(node);
}
}
}
文章评论