Natasha 4.0 探索之路系列(一) 概況

AzulX發表於2022-01-20

Natasha 簡介

  • Natasha 是一個基於 Roslyn 的動態編譯類庫, 它以極簡的 API 完成了動態編譯的大部分功能, 使用它可以在程式執行時編譯出新的程式集.
  • Natasha 允許開發人員直接使用 C# 程式碼即可編寫執行時的功能, 避免了 Emit 的學習,開發,維護的成本.
  • Natasha 的編譯單元的基本輸出是程式集, 程式集載入在域中, 使用該類庫可以建立域,並在不同的域內建立新的功能, 也支援可以解除安裝域.
  • Natasha 為開發人員提供了外掛管理的功能, 並內建解析依賴的功能, 我們可以有針對性的載入和解除安裝外掛及其依賴.
  • 使用 Natasha 我們可以快速的實現 mapper/類庫粘合/業務邏輯組裝/動態代理/協議轉換等等, 使用 Natasha 需要一定的程式設計基礎,有動態編譯經驗相關的實踐.儘管 Natasha 可以輸出詳細日誌,但是動態功能的開發本應該是邏輯暢通,程式碼規範的,如果你不能保證程式碼是暢通的,且沒有動態編譯的思維可以先找相關的文章進行學習.

專案連結地址: https://github.com/dotnetcore/Natasha

Natasha 進化

Natasha 自 v3.0.0 版本之後,進行了比較大的革新,以下我列舉一些比較重要的:

  • 移除對 standard2.0 / core2.1-3.0 的支援, 目前支援的版本為: net3.1/5.0/6.0, 相容版本已歸檔至其他分支.
    Runtime 是 Natasha 的強依賴, .NET 從 3.0 起, Runtime 升級了很多新的特性, 比如支援可空引用及後設資料處理, 支援 ALC 高階特性, 方便的外掛依賴解析方案等等, 另外由於個人精力有限, 最終決定從分水嶺 3.1 開始做相容.

  • 語義過濾, 自 v3.0.0 以後, Natasha 新增了語義層, 這讓 Natasha 顯得更加智慧, 我們可以根據自己的需求去解析和重組語法語義.
    比如 Natasha 內建的語義處理, 其中有一個功能是將無用的 using 移除掉, 只保留有用的 using. 大大減少了日誌輸出的程式碼, 讓開發者一眼看到有用的程式碼邏輯.
    編譯一段程式碼, 需要引用後設資料,需要準備 using,需要寫正確的程式碼,最後是輸出方式, 為了讓開發者以最快速度上手, Natasha 解決了後設資料引用問題,以及 using 覆蓋問題, 另對外提供了輸出 API, 理論上開發者需要關注的是自己如何編寫一段動態程式碼, 如何與執行時其他功能接洽配合.

    另針對名稱空間濫用導致的多義性引用問題, 我們提供了語義擴充套件包 Natasha.CSharp.Extension.Ambiguity

  • 效能優化, 優化是 Natasha 一直在做的事情, Natasha 在預熱方法上進行了一些併發的改造, 以便讓相互無關的任務並行初始化, 除此之外也移除了 AdWorkspace 程式碼, 這些帶碼均由高效能的方案取代. 針對效能敏感場景, 我們增加了預熱時全域性修剪錯誤語義,以及禁用語義過濾的 API, 以便讓編譯更快的發生.

  • 新特性支援. 支援 c# 最高語言版本, 支援可空引用的編譯(預設關閉), dll/pdb/xml 檔案手動選擇生成. Natasha 4.0 的原始碼使用了可空引用支援, 因此支援可空引用專案的接入和使用, 在方法呼叫的上下游明確了可空界限. 但在動態編譯層面,嘗試可空引用的後設資料解析功能時,我遇到了無法解決的難題, 可空引用的頂層泛型傳遞是無法正確解析的, 因此在 Action<string?> 等後設資料解析中,無法得到正確結果, 另外方法返回值可空引用解析也未找到方法, 綜上 Natasha 預設關閉了動態編譯初始化中的可空引用的選項, 開發者需要自行開啟.

  • 重構引用管理, 4.0 重構了 Natasha 的引用管理, 經過探索我們最終選定以 AssemblyName 作為引用版本管理的依據, 並在預熱過程中採用只讀上下文解析引用.

  • 重構外掛管理, 4.0 重構了 Natasha.Domain 域實現, 摘除了對引用管理的耦合, 讓 NatashaDomain 更專注於程式集及其依賴的載入與解除安裝, 此次對外提供了4個方法以便於使用者在載入外掛時管理不同版本的依賴.

  • 重構日誌模組, 4.0 版本後日志將由使用者自行控制寫入和獲取, 對外提供編譯後的日誌處理事件, Natasha 將不再負責日誌的 IO 部分.

  • 重構異常模組, 4.0 重構了 Natasha 的編譯單元, 其中語法轉換階段如果出錯會丟擲異常, 之後編譯不成功也會丟擲異常, 並提供編譯成功和失敗事件.


Natasha 實戰應用

Natasha 已經在網友公司及我司得到了廣泛應用, 比如:客戶端指令碼定製, 動態計分系統, 低程式碼應用中的邏輯組裝與編譯, 類庫中字串到表示式樹的轉換, 基於演算法的高效能只讀併發字典, 忽略類庫版本的程式碼粘合劑, 實體對映, 動態路由, 動態RPC, 動態定時任務等等.


Natasha 與其他技術

  • SG(Source Generetor)

首先來講 Natasha 與 SG 有重疊的部分, 但也有各自取代不了的地方. 我認為比較好的組合是, SG 提供靜態約束, Natasha 來提供動態實現.

  • AOT

Natasha 是儘可能覆蓋全面的程式集和引用, 剪裁需謹慎, 另外 AOT 不會取代動態編譯, 只會平行發展.


Natasha 未來規劃

Natasha 完成了自己的核心任務,但它還有很長一段的路要走, 期待大家的反饋.
後續 Natasha 還有一些方案需要調研, 一些應用需要開發, 例如:域的強制解除安裝方案, 基於 Asp.net 的動態開發框架, 高度靈活的高效能實體對映庫等.
下一篇將介紹 Natasha 的域元件與外掛程式設計.

相關文章