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

Natasha 簡介

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

項目鏈接地址: //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 的域組件與插件編程.