基於 Source Generators 做個 AOP 靜態編織小實驗
阿新 • • 發佈:2020-12-16
# 0. 前言
上接:用 Roslyn 做個 JIT 的 AOP
作為第二篇,我們基於Source Generators做個AOP靜態編織小實驗。
內容安排如下:
* source generators 是什麼?
* 做個達到上篇Jit 一樣的效果的demo
* source generators還存在什麼問題?
# 1. Source Generators 是什麼?
## 1.1 核心目的
開啟dotnet平臺的編譯時超程式設計功能,
讓我們能在編譯時期動態建立程式碼,
同時考慮IDE的整合,讓體驗更舒適。
官方文件:https://github.com/dotnet/roslyn/blob/master/docs/features/source-generators.md
展開我們思想的翅膀
我們能以此做各種事情:
* 生成實體json 等序列化器程式碼
* AOP
* 介面定義生成httpclient呼叫程式碼
* 等等
如下是官方認為會受益的部分功能列表:
* ASP.Net: Improve startup time
* Blazor and Razor: Massively reduce tooling burden
* Azure Functions: regex compilation during startup
* Azure SDK
* gRPC
* Resx file generation
* System.CommandLine
* Serializers
* SWIG
## 1.2 目前其設計和使用準則
允許開發者能在編譯時動態建立新增新程式碼到我們程式裡面
只能新增程式碼,不能修改已有程式碼
當無法生成源時,生成器應當產生診斷資訊,通知使用者問題所在。
可能訪問其他檔案非c#原始碼檔案。
無序執行模式,每個生成器都只能擁有相同的輸入編譯,即不能用其他生成器的生成結果進行再次生成。
生成器的執行類似於分析器。
# 2. 實驗:代理模式的靜態編織
## 2.1 建立一個Source Generators專案
```
```
## 2.2 建立SourceGenerator
需要繼承 `Microsoft.CodeAnalysis.ISourceGenerator`
```
namespace Microsoft.CodeAnalysis
{
public interface ISourceGenerator
{
void Initialize(InitializationContext context);
void Execute(SourceGeneratorContext context);
}
}
```
並通過[Generator]標識啟用
所以我們就可以做一個這樣的代理生成器:
```
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AopAnalyzer
{
[Generator]
public class ProxyGenerator : ISourceGenerator
{
public void Execute(SourceGeneratorContext context)
{
// retreive the populated receiver
if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
return;
try
{
// 簡單測試aop 生成
Action