跟著AI學習C# Day28

📅 Day 28:C# 源生成器(Source Generators)與編譯時元編程

? 學習目標:

  • 理解什么是 源生成器(Source Generator)
  • 掌握如何在 編譯階段生成 C# 代碼,而不是運行時動態處理;
  • 使用源生成器替代運行時反射和表達式樹,提升性能;
  • 實現一個基于源生成器的自動化 DTO 映射器;
  • 理解 Roslyn 編譯器的工作流程;
  • 掌握源生成器開發的基本結構、語法分析技巧;
  • 構建高性能、零運行時開銷的實用工具;
  • 了解源生成器的適用場景和局限性。

🧠 一、什么是源生成器?

源生成器(Source Generator) 是 C# 9 引入的一項新特性,它允許你在 編譯階段自動生成 C# 代碼。這些代碼會被加入到你的項目中,并參與正常的編譯流程,就像你手動編寫的一樣。

? 優勢:

特點說明
零運行時開銷所有邏輯在編譯期完成
更快的執行速度替代運行時反射、Expression 樹等慢速操作
更好的可讀性自動生成的代碼是靜態的,易于調試和優化
IDE 支持好可跳轉、可重構、可提示

🔁 二、源生成器 vs 運行時反射

對比項源生成器運行時反射
執行時機編譯期運行期
性能零開銷相對較慢
可維護性生成代碼可見動態邏輯難以追蹤
調試支持完全支持不易調試
是否需要額外依賴可能需要緩存或委托生成

🧩 三、源生成器基本結構

要創建一個源生成器,你需要實現 IIncrementalGenerator 接口(.NET 6+ 推薦),或者繼承 ISourceGenerator(舊版 .NET 5)。

我們以 .NET 6+IIncrementalGenerator 為例。

步驟概覽:

  1. 創建類庫項目并添加 SDK 支持;
  2. 添加對 Microsoft.CodeAnalysis.CSharpMicrosoft.CodeAnalysis.Analyzers 的引用;
  3. 實現 IIncrementalGenerator
  4. 注冊分析器并生成代碼;
  5. 在主項目中引用該源生成器 DLL;
  6. 查看生成的代碼(在 obj/Debug/generators 文件夾下)。

🛠? 四、實戰示例:自動映射 DTO 與實體類

我們來實現一個簡單的 DTO 映射器源生成器,它可以自動生成如下代碼:

public static class PersonMapper
{public static PersonDto ToDto(this Person person){return new PersonDto{Name = person.Name,Age = person.Age};}
}

1?? 定義 Attribute(用于標記需生成映射的類型)

[AttributeUsage(AttributeTargets.Class)]
public class GenerateMappingAttribute : Attribute
{public Type TargetType { get; }public GenerateMappingAttribute(Type targetType){TargetType = targetType;}
}

2?? 創建源生成器類

[Generator]
public class MappingSourceGenerator : IIncrementalGenerator
{public void Initialize(IncrementalGeneratorInitializationContext context){var classes = context.SyntaxProvider.CreateSyntaxProvider(predicate: static (s, _) => IsCandidateForMapping(s),transform: static (ctx, _) => GetSemanticTargetForMapping(ctx)).Where(static m => m is not null)!;context.RegisterSourceOutput(classes, GenerateCode);}private static bool IsCandidateForMapping(SyntaxNode node){return node is ClassDeclarationSyntax { AttributeLists.Count: > 0 };}private static ClassDeclarationSyntax GetSemanticTargetForMapping(GeneratorSyntaxContext context){var classDeclaration = (ClassDeclarationSyntax)context.Node;foreach (var attributeList in classDeclaration.AttributeLists){foreach (var attribute in attributeList.Attributes){if (context.SemanticModel.GetSymbolInfo(attribute).Symbol is IMethodSymbol attributeSymbol &&attributeSymbol.ContainingType.ToDisplayString() == "GenerateMappingAttribute"){return classDeclaration;}}}return null;}private void GenerateCode(SourceProductionContext context, ClassDeclarationSyntax classDecl){var className = classDecl.Identifier.Text;var namespaceName = classDecl.Parent is NamespaceDeclarationSyntax ns? ns.Name.ToString(): "";var source = $@"
using System;namespace {namespaceName}
{{public static partial class {className}Mapper{{public static {className}Dto ToDto(this {className} model){{return new {className}Dto{{Name = model.Name,Age = model.Age}};}}}}
}}";context.AddSource($"{className}Mapper.g.cs", SourceText.From(source, Encoding.UTF8));}
}

3?? 主項目使用方式

[GenerateMapping(typeof(PersonDto))]
public class Person
{public string Name { get; set; }public int Age { get; set; }
}public class PersonDto
{public string Name { get; set; }public int Age { get; set; }
}

編譯后會自動生成 PersonMapper 類!


🧱 五、Roslyn 編譯器基礎概念

源生成器基于 Roslyn 編譯器平臺,它是 C# 和 VB.NET 的開源編譯器框架。

關鍵組件:

名稱作用
SyntaxTree表示解析后的語法樹
SemanticModel提供語義信息(如變量類型、方法重載等)
Compilation表示整個項目的編譯過程
ISymbol表示各種符號(類、方法、屬性等)
GeneratorExecutionContext提供上下文信息用于生成代碼

💡 六、源生成器適用場景

場景示例
DTO 映射自動生成 ToDto() 方法
ORM 屬性綁定自動綁定數據庫字段
JSON 序列化避免反射,直接生成序列化代碼
本地化資源訪問自動生成強類型資源訪問器
日志記錄自動生成日志包裝器
AOP 攔截器生成代理類,替代運行時代理
枚舉擴展自動生成枚舉描述、轉換方法

?? 七、源生成器的限制

限制說明
不能訪問運行時數據無法根據用戶輸入動態生成代碼
不適合復雜邏輯復雜業務邏輯更適合運行時處理
調試困難生成的代碼位于 obj 文件夾,不易修改
學習曲線陡峭需要熟悉 Roslyn API 和語法樹結構
僅適用于編譯時已知結構的類型無法處理運行時動態類型

🧪 八、查看生成的代碼

生成的代碼會放在你的項目目錄下的:

[obj]\[Debug|Release]\net8.0\generators\run\Your.SourceGenerator\

你可以在這里看到所有由源生成器生成的 .g.cs 文件。


💪 九、構建高性能應用的建議

技術建議
盡量用源生成器替代反射減少運行時性能損耗
用源生成器預計算常量邏輯如路由匹配、配置加載
結合 Source Generator + Partial Method分離手寫邏輯與生成邏輯
使用緩存機制如果必須運行時處理,緩存結果
使用 Source Generator 生成測試樁自動生成 Mock 數據、單元測試輔助類

📝 小結

今天你學會了:

  • 什么是 源生成器(Source Generator)
  • 掌握了如何在 編譯階段生成 C# 代碼
  • 實現了一個基于源生成器的 自動 DTO 映射器
  • 理解了 Roslyn 編譯器的基本工作原理;
  • 掌握了源生成器開發的基本結構和語法分析技巧;
  • 學會了如何構建高性能、零運行時開銷的實用工具;
  • 了解了源生成器的適用場景與限制。

源生成器是一項強大的工具,尤其適用于構建高性能框架、減少運行時反射依賴、以及自動完成重復性代碼編寫任務。


🧩 下一步學習方向(Day 29)

明天我們將進入本次 挑戰的 最終總結篇 —— C# 綜合進階知識回顧與職業發展建議,你將學到:

  • 所學知識點的系統回顧;
  • 如何構建完整的 C# 開發能力體系;
  • C# 高級開發者必備技能清單;
  • C# 在 Web、桌面、游戲、AI 等領域的應用場景;
  • 如何規劃自己的 C# 職業成長路徑;
  • 如何準備技術面試、參與開源項目、打造個人影響力。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/910273.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/910273.shtml
英文地址,請注明出處:http://en.pswp.cn/news/910273.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

設計模式精講 Day 4:建造者模式(Builder Pattern)

【設計模式精講 Day 4】建造者模式(Builder Pattern) 文章簡述: 在軟件開發中,對象的構造過程往往復雜且容易出錯,尤其是在對象包含多個可選參數或構建步驟時。建造者模式(Builder Pattern)正是…

如何輕松地將聯系人從 iPhone 轉移到 iPhone?

也許您升級到最新的 iPhone 型號,或者需要切換到另一部 iPhone 來工作。無論如何,您不能錯過您的聯系人,這對每個人來說都是最重要的數據。因此,今天我們將分享 5 種如何將聯系人從 iPhone 轉移到 iPhone 的方法,幫助您…

【51單片機簡單的流水燈程序問題】2022-5-24

1.利用單片機的P2口接8個發光二極管。簡單的流水燈程序問題-編程語言-CSDN問答 2.發光二極管自由閃爍(自己設計兩種模式)。 3.可通過按鍵實現暫停、啟動以及不用模式的切換。 4. 利用Proteus繪制電路原理圖 5. 元件選型&#xff1…

第七節:Vben Admin 最新 v5.0 (vben5) 快速入門 - 用戶管理(上)

Vben5 系列文章目錄 ?? 基礎篇 ? 第一節:Vben Admin 最新 v5.0 (vben5) 快速入門 ? 第二節:Vben Admin 最新 v5.0 (vben5) 快速入門 - Python Flask 后端開發詳解(附源碼) ? 第三節:Vben Admin 最新 v5.0 (vben5) 快速入門 - 對接后端登錄接口(上) ? 第四節:Vben Ad…

1572. 矩陣對角線元素的和

給你一個正方形矩陣 mat,請你返回矩陣對角線元素的和。 請你返回在矩陣主對角線上的元素和副對角線上且不在主對角線上元素的和。 示例 1: 輸入:mat [[1,2,3],[4,5,6],[7,8,9]] 輸出:25 解釋:對角線的和為&#xf…

供應鏈場景使用ClickHouse最佳實踐

一、概述 ClickHouse是一款由俄羅斯公司Yandex開發的開源列式數據庫管理系統,以其高性能的分析查詢能力和高壓縮比著稱。供應鏈場景中,數據量大且數據類型復雜,需要高效的數據存儲和快速的查詢性能,ClickHouse在這些方面具有顯著…

RA4M2開發IOT(0)----安裝e2 studio

RA4M2開發IOT.0--安裝e studio 概述視頻教學樣品申請安裝 概述 瑞薩電子靈活配置軟件包 (FSP) 是用于嵌入式系統設計的高質量增強型軟件包,支持瑞薩電子 RA 產品家族 Arm 微控制器,提供用戶友好的界面且可靈活擴展,確保從入門級到高性能的整…

【Ambari3.0.0 部署】Step2—免密登陸認證-適用于el8

如果有其他系統部署需求可以參考原文 戳我->所有組件編譯教程 戳我->獲取部署源代碼 一、免密登錄認證 🔐 在多臺服務器協同工作的環境中,免密登錄(SSH 免密認證)是一種常見的優化手段,能夠極大地提升運維效率&…

網站自助廣告投放系統源碼 附安裝教程(源碼下載)

網站自助廣告投放系統源碼 全自動無人化出售網站廣告位 站長必備 源碼測試可用,部分加密。感興趣自行下載 源碼下載:https://download.csdn.net/download/m0_66047725/91093092 更多資源下載:關注我 圖片:

日常運維問題匯總-15

42.SD開票計劃產生的預收款在正式開票時未自動清賬 統馭科目(應收、預收)對應的字段狀態組中附加科目設置銷售訂單字段設置為了隱藏導致,更改為“可選輸入項” 43.MIGO取消憑證時,用戶反饋發現除一行外,其它都不能取消…

【設計模式】6.原型模式

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 原型模式 1. 基礎 import copyclass Resume:def __init__(self, name):self.name nameself.sex Noneself.age Noneself.time_area Noneself.compan…

【算法 day08】LeetCode 151.翻轉字符串里的單詞 |卡碼網:55.右旋轉字符串

151.翻轉字符串里的單詞 題目鏈接 | 文檔講解 |視頻講解 : 鏈接 1.思路: 1.去除字符串頭尾的空格 ,使用庫函數 trim() 2.對字符串進行分割,使用庫函數split() 3.創建StringBuilder sb&#x…

【WordPress優化插件】WPOPT v2.4.7

WPOPT插件,是由本站開發的一款WordPress優化插件,能對WordPress底層功能進行優化,支持功能開關,系統加速等功能。 2.0版本全新發布,采用vite打包,界面采用Vue3+element-plus制作。無論是外觀,還是框架功能,都是空前的強大。 功能更多,更強,是所有WordPress網站都值得…

如何使用 mkimage 工具生成 uImage 文件(RISC-V 環境)

一、mkimage 命令參數詳解 在 RISC-V Linux 環境下,使用 U-Boot 的 mkimage 工具生成 uImage 的基本命令格式如下: mkimage -A riscv -O linux -T kernel -C compression -a load_addr -e entry_addr -n "描述信息" -d Image uImage核心參數…

React Native 搭建iOS與Android開發環境

目錄 第一步 第二步 一、必須安裝的工具 二、具體安裝步驟 1. 安裝 Homebrew 切換國內源和其他配置: 2. 安裝 node 3.下載watchman 4. Ruby 5.CocoaPods 配置環境 6. jdk 7. 配置git 開發環境 第三步——啟動項目(可以忽略) 1…

Vue 簡寫形式全解析:清晰記憶指南

Vue 簡寫形式全解析:清晰記憶指南 Vue 中的各種簡寫形式確實容易混淆,我將它們系統化整理,并提供了多種記憶方法,幫助你輕松掌握! 一、核心簡寫形式匯總表 完整形式簡寫形式適用場景記憶技巧v-bind:attribute:attribute動態綁定屬性: 像鏈條,表示"綁定"v-on:…

車載電子電器架構 --- 電子電氣架構設計方案

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

MVCC中read_view的核心參數解析與讀操作流程實戰

在數據庫并發控制領域,MVCC(多版本并發控制)是實現高性能讀寫并發的關鍵技術。其中,read_view作為MVCC判斷數據可見性的核心組件,其內部參數的設計直接影響著并發訪問的行為。本文將深入解析read_view的三個核心參數&a…

從代碼學習深度強化學習 - REINFORCE 算法 PyTorch版

文章目錄 前言**一、 理論基礎:什么是策略梯度?****1.1 基于價值 vs. 基于策略****1.2 策略梯度(Policy Gradient)****1.3 REINFORCE 算法:蒙特卡洛策略梯度****1.4 REINFORCE 算法流程****二、 PyTorch 代碼實踐****2.1 環境與輔助函數****2.2 核心算法實現****2.3 訓練與…

CRMEB 代碼規范指南:ThinkPHP6+Uni-app 架構下的開發標準

二、代碼規范 2.1 Vue .1.1 代碼結構 <template><div id"my-component"><DemoComponent /></div> </template><script> import DemoComponent from ../components/DemoComponentexport default {name: MyComponent,component…