文章轉載授權級別:A 預計閱讀時間:15分鐘
文章轉載自公眾號【NCC開源社區】 ,作者 【】
一、 2.0預覽版本增加了哪些功能
大部分為底層的升級優化,例如:
構建方面的強化 , 例如:
二、我們經歷了哪些實踐
深度克?。?com/night-moon-/
本項目由 、Vito、、白開水組隊開發,可在運行時動態生成克隆方法 。深度克隆作為基礎項目 , 鍛煉了開源工作者的類型辨識技能 , 趟過了坑為以后的封裝之路打下基礎 。
【「A」兼容Core3.0后 Natasha 的隔離域與熱編譯操作】快速調用:.com/night-moon-/
本項目由 AzulX 和 * 開發,可以對運行時實體類、靜態類的字段/屬性進行動態調用和賦值,目前有兩個主要分支,哈希二叉查找算法動態實現以及 * 的指針二叉查找算法動態實現,在算法的動態實現上 , 表現出了相當強大的優勢 。
三、談一談‘熱更新’
‘熱更新’是 Core3.0 的亮點特性之一 , 不少小伙伴在看到譯文的時候可能就已經想到了N多場景 , 歷經兩代 .NET 的洗禮,‘熱更新’現在發展到什么樣子了?下面簡單談一談:
.NET開荒時期有域之隔離術,包括有創建、加載程序集、卸載等方法,囊括百家程序集在以下哪個場景中推薦使用wisp,一刀以斬之 。對于前輩們來說談到可以口若懸河滔滔不絕,可惜我進入 C# 時間比較晚,對的印象并不是很深,在應用上也沒有什么造詣在以下哪個場景中推薦使用wisp,僅此泛泛而言 。
時間進入了 . 時代,在升級大潮中受到了致命打擊 , 方法和方法經歲月升級后的源碼中充斥著 throw 和 throw,完全喪失了功能,取而代之的是 ALC(),Core3.0 的 ALC 是一個更為完善的操作類,官方為其定義了三大洪荒場景:
1、插件編程
2、動態編譯 , 運行/刷新代碼,網站/腳本引擎
3、外部程序集的一次性內?。ㄎ腋鋈死斫餼褪搶嗟男畔?,,這種元數據只讀屬性)
據描述: 之前一直用, 每個測試都腰酸背痛相當慢,自從換了 ALC( A blue Ca.) 一口氣上5樓不費勁!官方畫了大餅:未來分析器執行編譯時也都在ALC里進行,用完就卸載,卸磨就殺驢 。
當初被定位在高性能、安全,歷史證明這個定位跟 GPS 一樣不準,ASP.NET 深受其害,歷史車輪碾過了 ASP.NET 迎來了 ASP.NET Core,在域功能被閹割的期間 , ASP.NET Core 轉向了相對靜態的模型,增加了若干學習成本,詳見watch 命令 。還有 Razor , 它從 . 編譯到 .dll 的環境就是 ALC,自建了一個名為 Razor- 的域環境 。
另外還涉及到和 Prism 框架, 精力有限,誰有興趣就去研究研究吧 。
ALC 的場景和案例可能激起了您的好奇心,下面講一下 ALC 的應用:
我們可以在程序里創建多個 ALC 實例 , 但前提是你需要繼承并實現它 。每一個 ALC 的實例都是一個域(這里我就不叫它上下文了) 。程序剛跑起來的時候是在域中的,這個域屬于系統域卸不了,又稱為共享域,不同域之間是無法訪問和引用的不同域中信息的,卻共用域中的信息,這個域至關重要,所以盡量避免向其中加載亂七八糟的程序集 。
ALC 的使用需要注意以下幾點:
1、子類繼承時需指定 ALC 的構造參數,base() , 這個參數可以賦予 ALC 卸載的能力 。
2、時刻注意反射信息的引用,只有清除引用,才能保證 ALC 實例被 GC 回收 。
3、在針對不同域的編程時可使用 ction 方法鎖住域內上下文,ction 方法是放在 using 里的,這樣你的花括號內就是一個域 , 并用屬性來獲取當前操作域 。
4、注意 ALC 被線程占用的情況 , 被占用的對象是無法被回收的,如果你在測試中沒有達到預期,除了排除代碼問題之外你還需要注意函數是否被內聯進入主線程或一個帶有阻塞功能的線程 , 如果你不確定 , 可以在方法上使用 [(.)] 阻止代碼內聯優化 , 正常情況下優化功能是開啟的。
5、插件加載要注意與插件 dll 同目錄的依賴文件,3.0 提供了操作類自動解析依賴,建議使用帶有.deps.json文件的完整插件 。
6、當你的外部文件引用并使用了 / 等(測試日期9月3日),會造成不可回收的情況,不是你的代碼出問題了 , 而是庫本身的問題(待解決,3.1或者5.0) 。
對 ALC 封裝的一些建議:
1、如果沒有非托管代碼,盡量不要在析構函數里折騰代碼 。
2、如果你的域管理代碼有些復雜 , 建議對外給個接口,以便清除對該域的程序集、元數據等信息的引用 。
3、肉眼觀測內存時,測試代碼中盡量不要在 Main 函數里做元數據的相關操作 , 主線程是 GC 的一個干擾點 。
4、若對內存的開銷比較敏感,請盡可能分域,并結合弱引用實現創建與銷毀 。
5、有時顯式調用方法會報異常,可以在里清除完引用之后再使用,實測你不用方法也能回收 。
Core3.0 中隨 ALC 一起的還有反射的自省信息 。
例如:.、.等元數據,它將告訴你它是否能被回收,當然了這種自省的信息都是只讀的 。說到只讀 , .NET 中還存有一條進化路線即 : ->->(感謝提供的信息), 只讀元數據,相比 ALC 可執行,可調用,MLC (在包 .. 中) 的是元數據只讀操作,它并不能執行程序集的內容 , 僅僅反射出元數據,配套使用的是.
對于無法卸載的情況,官方建議使用sos 組件進行調試,新版 sos 將獨立出來,各位可以使用以下命令進行安裝(建議開源工作者在封裝此功能時添加UT測試檢測卸載功能,盡可能保證在正常的情況下不需要用戶自己去調試) 。
$ dotnet tool install -g dotnet-sos --version 3.0.0-preview8.19412.1
$ dotnet-sos install
更多的實踐還需要大家去探索 。
四、是如何實現‘熱更新’的
據以上信息,.0 中動態構建遵循以下結構 。
這兩幅圖說展示了中自定義編譯域的結構,如果在創建程序集時不指定名字,程序集名將以 GUID 形式創建,故名隨機程序集 。在編譯時未被移除的引用都將參與編譯 , 該引用的來源:1、共享域;2、當前域;
//創建一個域DomainManagment.Create("MyDomain");//移除一個域,移除將無法進行DomainManagment的其他任何操作DomainManagment.Remove("MyDomain");//判斷域是否被卸載(被GC回收)DomainManagment.IsDeleted("MyDomain");//獲取一個ALC上下文DomainManagment.Get("MyDomain");//鎖住已存在的域上下文using(DomainManagment.Lock("MyDomain")){ var domain = DomainManagment.CurrentDomain; //code in 'MyDomain' domain }//創建并鎖定一個域上下文using(DomainManagment.CreateAndLock("MyDomain")){ var domain = DomainManagment.CurrentDomain; //code in 'MyDomain' domain }
//向域中注入插件 string dllPath = @"1/2/3.dll";var domain = DomainManagment.Get/Create("MyDomain");var assembly = domain.LoadFile(dllPath);//鎖域與插件解構操作string dllPath = @"1/2/3.dll";using(DomainManagment.CreateAndLock("MyDomain")){ var (Assembly,TypeCache) = dllPath; //Assembly: Assembly //TypeCache: ConcurrentDictionary }//將引用從當前域內移除,下次編譯將不會帶著該程序集的信息//下面方法三選一均可實現引用移除操作domain.RemoveDll(dllPath);domain.RemoveAssembly(assembly);domain.RemoveType(type);
//從指定域創建一個程序集操作實例var asm = domain.CreateAssembly("MyAssembly");//向程序集中添加一段已經寫好的類/結構體/接口/枚舉asm.AddScript(@"using xxx; namespace xxx{xxxx}");asm.AddFile(@"Class1.cs");//使用Natasha內置的操作類asm.CreateEnum(name=);asm.CreateClass(name=);asm.CreateStruct(name=);asm.CreateInterface(name=);//使用Natasha內置的方法操作類//并不是很推薦使用這兩個方法//建議在一個單獨的程序集內編譯方法 asm.CreateFastMethod(name=);asm.CreateFakeMethod(name=);//使用程序集進行編譯并獲得程序集var assembly = asm.Complier;asm.GetType(name);
using(DomainManagment.CreateAndLock("MyDomain")){ var domain = DomainManagment.CurrentDomain; var assembly = domain.CreateAssembly("MyAssembly"); //創建一個接口 assembly .CreateInterface("InterfaceTest") .Using("System") .OopAccess(AccessTypes.Public) .OopBody("string ShowMethod(string str);"); //創建一個類并實現接口 assembly .CreateClass("TestClass") .Using("System") .OopAccess(AccessTypes.Public) .Inheritance("InterfaceTest") .Method(method => method .MemberAccess(AccessTypes.Public) .Name("ShowMethod") .Param("str") .Body("return str+" World!";") .Return); //編譯并獲取類型 var result = assembly.Complier; var type = assembly.GetType("TestClass"); //Operator默認單獨創建一個程序集 var @delegate = FastMethodOperator.New .Using(type) .MethodBody(@" TestClass obj = new TestClass; return obj.ShowMethod(arg);") .Complie<Func>; @delegate("Hello"); //result = "Hello World!"; domain.Dispose; //卸磨殺驢}
不要從公眾號里復制代碼到VS , 會有意外字符 。
五、Bug有緣人
訪問以下鏈接:.com///blob//src/../src///..cs
自右向左選中, 如果頁面崩潰了, 老鐵握爪 。
.com/
打賞一杯酒,削減三分愁 。跟著我們走,脫發包你有 。
組織打賞賬戶為檸檬的賬戶,請標注「NCC」 , 并留下您的名字,以下地址可查看收支明細:.com//Home/blob//-of–and-.md
,專注.NET技術的公眾號
.xyz
微信ID:
歡迎打賞組織
給予我們更多的支持
本文到此結束,希望對大家有所幫助 。
- ?今后坐地鐵2號線可直達火車站嘛「今后坐地鐵2號線可直達火車站」
- 如果有一天QQ,微信不兼容iOS了,你會選騰訊還是蘋果?
- ?沈陽公交車停運最新消息「剛剛發布3月22日至23日12時沈陽公交地鐵暫停提倡居
- ?為什么坐地鐵喜歡坐兩邊「上地鐵選座位兩頭位置的人是什么心理」
- 「微黨務」民主生活會上如何提批評意見?
- 「Win」新系統安裝好后一定要設置的地方,減少后期系統問題
- 「去父留子」新型婚育觀:父親們該何去何從?
- 「U盤重裝系統」PE系統盤制作
- 「教育故事」遇到心智不夠成熟的孩子怎么辦?
- 「裝機必備」一款必備的解壓縮工具
