天天看點

動态程式設計神器! 探秘.Net中的AI時代秘密武器——Natasha架構全解析

作者:opendotnet

在開發領域,我們經常會遇到需要動态加載和執行代碼的場景。對于Python、JavaScript、Lua等腳本語言,動态性是它們的天性,而對于需要預先編譯的語言,如C#,動态執行似乎并不那麼直覺。但随着AI的普及,例如我們想在C#程式中動态執行AI生成的代碼段,這就要求我們能在運作時編譯和執行C#代碼。接下來,讓我為你介紹一個強大的架構——Natasha。

Natasha:動态地建構你的.Net世界

Natasha是一個基于Roslyn的C#動态程式集建構庫。它允許開發者在程式運作時動态地建構域、程式集、類、結構體、枚舉、接口和方法等。這意味着開發者可以在不停止應用程式的情況下,為其增加新的程式集。

Natasha架構具備域管理和插件管理功能,支援域的隔離和解除安裝,實作了熱插拔。它提供了完善的錯誤提示,自動添加引用,并且擁有完整的資料結構構模組化闆,進而讓開發者專注于程式集腳本的編寫。更何況它還有着跨平台的優勢,并且對netcoreapp2.0+ / netcoreapp3.0+都相容。

動态程式設計神器! 探秘.Net中的AI時代秘密武器——Natasha架構全解析

Natasha的使用場景

你可能會好奇,這樣一個動态編譯庫是如何彰顯其價值的?其實,動态編譯技術是支撐如今.NET生态不可或缺的重要部分。無論是在官方還是非官方的庫中,動态編譯的技術都扮演着“服務”的角色。其核心是MSIL,官方為我們提供了Emit技術來編寫IL代碼。但Emit的編寫和維護并不友好,給開發者帶來了諸多挑戰。

Roslyn的出現仿佛開啟了新世界的大門,它使得Emit變得透明,并允許我們直接用C#進行動态編譯。Natasha就是在這樣的基礎上發展起來的,經過精心設計與不斷疊代,它正成為動态編譯領域的佼佼者。

Natasha的簡單應用場景

借助Natasha,你可以實作衆多有趣而實用的功能,如建立AOP代理類或動态建構Controller來實作動态API,甚至在程式啟動時與CodeFirst相容的ORM一起使用,動态建立表結構,甚至通過動态執行AI建立的代碼段,這是個非常有趣的事情!

不可否認,這些功能的實作需要一定的程式設計基礎。例如,下面的代碼展示了如何使用Natasha快速開始一個域,并利用其插件管理功能。

// 開始建立域              var domain = new NatashaDomain();              // 建立非主域              var domain = new NatashaDomain(key);                  // 加載插件              var assembly = domain.LoadPlugin(pluginPath);                  // 使用程式集比較器              domain.SetAssemblyLoadBehavior(AssemblyCompareInfomation.UseHighVersion);                  // 封裝API              domain.LoadPluginWithHighDependency(PluginPath);           

在智能編譯模式下,你可以使用如下代碼快速地進行編譯,Natasha将智能地合并中繼資料和Using聲明,并進行語義檢查。

AssemblyCSharpBuilder builder = new AssemblyCSharpBuilder();              var myAssembly = builder.UseRandomDomain()              .UseSmartMode()              .Add("public class A{ }")              .GetAssembly();           

Natasha的輕便編譯模式

對于更加輕便的編譯需求,Natasha提供了簡潔編譯模式。該模式會合并目前域的中繼資料和Using聲明,并關閉語義檢查,提供一種更加靈活快速的編譯方式。

AssemblyCSharpBuilder builder = new AssemblyCSharpBuilder();              var myAssembly = builder.UseRandomDomain()              .UseSimpleMode()              .Add("public class A{ }")              .GetAssembly();           

中繼資料管理與微調

Natasha也提供了完整覆寫和部分覆寫引用和using代碼的能力。例如,合并共享域的引用和using代碼可以使用以下方法:

builder.WithCombineReferences(item => item.UseAllReferences());              builder.WithCombineUsingCode(UsingLoadBehavior.WithAll);           

如果希望合并目前域的引用和using代碼或者使用自定義的引用,可以使用如下方法:

builder.WithCurrentReferences();              builder.WithCombineUsingCode(UsingLoadBehavior.WithCurrent);              // 使用自定義的中繼資料引用              builder.WithSpecifiedReferences(someMetadataReferences);           

腳本教程

對于編寫和加載腳本,Natasha采用靈活的配置API來覆寫using代碼,并添加編譯選項。這允許開發者指定腳本中要使用的C#語言版本,以及如何處理using指令。

// 配置語言版本              builder.ConfigSyntaxOptions(opt => opt.WithLanguageVersion(LanguageVersion.CSharp6));              // 添加腳本并覆寫Using Code              builder.WithCombineUsingCode(UsingLoadBehavior.WithAll).Add(myCode);              // 自定義覆寫Using Code              builder.Add("script", UsingLoadBehavior.WithCurrent);           

進階編譯技巧

Natasha提供了一系列的With、Set和Config系列API來精細控制編譯過程。你可以配置編譯選項、診斷資訊級别,甚至啟用或關閉某些特殊的編譯行為。例如,啟用語義檢查或添加語義處理插件:

// 啟用語義檢查              builder.WithSemanticCheck();              //增加語義處理插件              builder.AddSemanticAnalysistor();           

動态調試

使用Natasha進行動态源代碼調試是輕而易舉的。開啟調試模式可以幫助你更深入地了解代碼執行情況,Natasha提供了多種選項來寫入調試資訊:

builder.WithDebugCompile(item => item.WriteToFile()); // 調試資訊寫入檔案              builder.WithDebugCompile(item => item.WriteToAssembly()); // 調試資訊整合到程式集              builder.WithReleaseCompile(); // 設定為Release模式           

生成程式集

在程式集被編譯前,你可以使用Natasha提供的API來進行各種配置,比如設定程式集名稱或輸出選項:

builder.SetAssemblyName("MyAssembly");              builder.WithSemanticCheck(); // 啟用語義檢查              builder.WithFileOutput("path/to/dll", "path/to/pdb", "path/to/xml"); // 檔案輸出配置           

使用 Codecov 的擴充

Natasha還提供了一個Codecov擴充,可幫助你擷取代碼覆寫率資料。首先你需要引入

DotNetCore.Natasha.CSharp.Extension.Codecov

擴充包,然後像下面這樣使用:

builder.WithCodecov();              Assembly asm = builder.GetAssembly();              List<(string MethodName, bool[] Usage)>? coverageData = asm.GetCodecovCollection();              Show(coverageData);           

上面的

Show

方法将周遊并顯示每個方法的執行情況。這是一種很好的方式來監測你的代碼如何執行,確定品質和可靠性。

Natasha 的類型擴充

最後,Natasha提供了類型擴充來幫助你更輕松地處理類型資訊。例如,擷取運作時或開發時的類型名稱,或者檢查類型是否實作了某個接口:

typeof(Dictionary<string,List<int>>[]).GetRuntimeName(); // 擷取運作時類型名稱              typeof(Dictionary<string,List<int>>).IsImplementFrom<IDictionary>(); // 檢查是否實作指定接口           

當然這個項目也是開源的,不論是學習思路還是代碼設計方案 ,檢視下面的項目位址都是不錯的選擇

https://github.com/dotnetcore/Natasha           

後面我會使用Natasha嘗試通過AI來生成c#代碼并動态執行,可以關注我,并持續關注我的下一步行動!

繼續閱讀