摘要:
作為《ASP.NET Core 3框架揭秘》的升級版,《ASP.NET Core 6框架揭秘》提供了很多新的章節,同時對現有的內容進行大量的修改。雖然本書旨在對ASP.NET Core框架的架構設計和實現原理進行剖析,但是其中提供的258個實例演示卻可以作為入門材料,這個系列會將這些演示實例單獨提取 閱讀全文
posted @ 2022-02-22 08:23
Artech
閱讀(28978)
評論(8)
推薦(63)
參數在方法種具有按“值(by value)”和“引用(by ref)”兩種傳遞方式,這是每個.NET程序員深入骨髓得基本概念。但是我若告訴你,.NET規定的參數傳遞形式其實是三種,會不會顛覆你的認知。 閱讀全文
在《可以調用Null的實例方法嗎?》一文中,我談到.NET方法的三種調用形式,現在我們就來著重聊聊這個話題。具體來說,這里所謂的三種方法調用形式對應著三種IL指令:Call、CallVirt和Calli。 閱讀全文
前幾天有個網友問我一個問題:調用實例方法的時候為什么目標對象不能為Null。看似一個簡單的問題,還真不是一句話就能說清楚的。而且這個結論也不對,當我們調用定義在某個類型的實例方法時,目標對象其實可以為Null。 閱讀全文
當我們使用System.Text.Json.JsonSerializer對一個字典對象進行序列化的時候,默認情況下字典的Key不能是一個自定義的類型,本文介紹幾種解決方案。 閱讀全文
毫不夸張地說,路由是ASP.NET Core最為核心的部分。路由的本質就是注冊一系列終結點(Endpoint),每個終結點可以視為“路由模式”和“請求處理器”的組合,它們分別用來“選擇”和“處理”請求。請求處理器通過RequestDelegate來表示,但是當我們在進行路由編程的時候,卻可以使用任意類型的Delegate作為處理器器,這一切的背后是如何實現的呢? 閱讀全文
ASP.NET Core MVC的“模塊化”設計使我們可以構成應用的基本單元Controller定義在任意的模塊(程序集)中,并在運行時動態加載和卸載。《設計篇》介紹了這種為“飛行中的飛機加油”的方案的實現原理?本篇我們將演示將介紹“分散定義Controller”的N種實現方案。源代碼從這里下載。 閱讀全文
ASP.NET Core MVC的“模塊化”設計使我們可以構成應用的基本單元Controller定義在任意的模塊(程序集)中,并在運行時動態加載和卸載。這種為“飛行中的飛機加油”的方案是如何實現的呢?該系列的兩篇文章將關注于這個主題,本篇著重介紹“模塊化”的總體設計,下篇我們將演示將介紹“分散定義Controller”的N種實現方案。 閱讀全文
ControllerModel類型的Actions屬性包含一組描述有效Action方法的ActionModel對象。對于定義在Controller類型中的所有方法,究竟哪些方法才能成為有效的Action方法呢?所以在正式介紹ActionModel類型之前,我們先來聊聊Action方法的選擇規則。 閱讀全文
從編程的角度來看,一個MVC應用是由一系列Controller類型構建而成的,所以對于一個代表應用模型的ApplicationModel對象來說,它的核心就是Controllers屬性返回的一組ControllerModel對象,每個ControllerModel對象是應用模型針對Controller類型的描述。 閱讀全文
在對應用模型的基本構建方式具有大致的了解之后,我們來系統地認識一下描述應用模型的ApplicationModel類型。對于一個描述MVC應用模型的ApplicationModel對象來說,它承載的元數據絕大部分是由默認注冊的DefaultApplicationModelProvider對象提供的,在接下來針對ApplicationModel及其相關類型(ControllerModel、ActionModel和ParameterModel等)的介紹中,我們還會著重介紹DefaultApplicationModelProvider對象采用怎樣的方式提取并設置這些元數據。 閱讀全文
我個人覺得這是ASP.NET Core MVC框架體系最核心的部分。原因很簡單,MVC框架建立在ASP.NET Core路由終結點上,它最終的目的就是將每個Action方法映射為一個或者多個路由終結點,路由終結點根據附加在Action上的若干元數據構建而成。為了構建描述當前應用所有Action的元數據,MVC框架會提取出定義在當前應用范圍內的所有Controller類型,并進一步構建出基于Controller的應用模型。應用模型不僅僅是構建Action元數據的基礎,承載API的應用還可以利用它自動生成API開發文檔,一些工具甚至可以利用應用模型自動生成消費API的客戶端代碼。 閱讀全文
我想很多人已經體驗過GRPC提供的三種流式消息交換模式,在.NET Core上構建的GRPC應用本質上是采用HTTP2/HTTP3協議的ASP.NET Core應用,我們當然也可以在一個普通的ASP.NET Core應用實現這些流模式。不僅如此,HttpClient也提供了響應的支持,這篇文章通過一個簡單的實例提供了相應的實現 閱讀全文
針對“緩沖區”編程是一個非常注重“性能”的地方,我們應該盡可能地避免武斷地創建字節數組來存儲讀取的內容,這樣不但會導致大量的字節拷貝,臨時創建的字節數組還會帶來GC壓力。要正確、高效地讀寫緩沖內容,我們應該對幾個我們可能熟悉的類型具有更深的認識。 閱讀全文
由于Memory存儲的是單純的二進制字節,所以原則上我們可以用來它作為媒介,在wasm模塊和數組程序之間傳遞任何類型的數據。在JavaScript API中,Memory通過WebAssembly.Memory類型表示,我們一般將它內部的緩沖區映射相應類型的數組進行處理。WebAssembly也提供了相應的指令來提供針對Memory的讀、寫、擴容等操作 閱讀全文
WebAssembly程序總是以模塊來組織,模塊是基本的部署、加載和編譯單元。在JavaScript編程接口中,模塊通過WebAssembly.Module類型表示。WebAssembly.Module通過加載的.wasm二進制文件創建而成,它承載了描述wasm模塊的元數據,類似于描述程序集的Assembly對象。WebAssembly.Module自身是只讀且無狀態的,有狀態的是根據它結合指定的導入對象創建的模塊實例,后者通過WebAssembly.Instance表示。這兩個類型提供了幾個核心API,解析我們就通過它們來介紹WebAssembly的這兩個核心對象。 閱讀全文
對于絕大多數編程語言來說,類型都是編程的基礎,WebAssembly自然也不例外。總的來說,WebAssembly涉及的類型不多,很好掌握,接下來我們就來介紹一下WebAssembly編程涉及到的幾種類型。本篇內容參考WebAssembly Spec。 閱讀全文
當我們在一個Web應用中使用WebAssembly,最終的目的要么是執行wasm模塊的入口程序(通過start指令指定的函數),要么是調用其導出的函數,這一切的前提需要創建一個通過WebAssembly.Instance對象表示的wasm模塊實例(源代碼)。 閱讀全文
利用WebAssembly的導入導出功能可以靈活地實現宿主JavaScript程序與加載的單個wasm模塊之間的交互,那么如何在宿主程序與多個wasm之間傳遞和共享數據呢?這就需要使用到Global這個重要的對象了。 閱讀全文
在《WebAssembly入門筆記[2]》中,我們介紹了如何利用Memory在作為宿主的JavaScript應用和wasm模塊之間傳遞數據,但是Memory面向單純二進制字節的讀寫在使用起來還是不太方便,此時我們會更多地用到另一個重要的對象Table。Table利用用來存儲一組指定類型的對象,說得準確一點是對象的引用,所以可以讀取出來直接消費。 閱讀全文
利用靈活的“導入”和“導出”機制,WebAssembly與承載的JavaScript應用之間可以很便利地“互通有無”。《與JavaScript的交互》著重演示了如何利用函數的導入和導出實現功能的共享,接下來我們主要關注數據的傳遞或者共享。宗地來說,WebAssembly與宿主程序之間的數據傳遞主要有如下三種手段,本篇文章主要關注Memory。 閱讀全文
前一陣子利用Balazor開發了一個NuGet站點,對WebAssembly進行了初步的了解,覺得挺有意思。在接下來的一系列文章中,我們將通過實例演示的方式介紹WebAssembly的一些基本概念和編程模式。 閱讀全文
前幾天有人在我的《ASP.NET Core框架揭秘》讀者群跟我留言說:“我最近在看ASP.NET Core MVC的源代碼,發現整個系統太復雜,涉及的東西太多,完全找不到方向,你能不能按照《200行代碼,7個對象——讓你了解ASP.NET Core框架的本質》這篇文章思路剖析一下MVC框架”,今天我們就來試試看。 閱讀全文
在過去一段時間里,我陸陸續續寫一些關于.NET對象類型布局的文章,其中包括值類型和引用類型的內存布局、字符串對象和數組的內存布局等,這里作一個簡單的匯總。 閱讀全文
在《NativeBuffering,一種高性能、零內存分配的序列化解決方案[性能測試篇]》我比較了NativeBuffering和System.Text.Json兩種序列化方式的性能,通過性能測試結果可以看出NativeBuffering具有非常明顯的優勢,有的方面的性能優勢甚至是“碾壓式”的,唯獨針對字符串的序列化性能不夠理想。我趁這個周末對此做了優化,解決了這塊短板,接下來我們就來看看最新的性能測試結果和背后“加速”的原理。 閱讀全文
.NET利用ArrayPoolPool<T>和MemoryPool<T>提供了針對Array/Memory<T>的對象池功能。最近在一個項目中需要使用到針對字節數組的對象池,由于這些池化的字節數組相當龐大,我希望將它們分配到POH上以降低GC的壓力。由于ArrayPoolPool<T>沒法提供支持, 閱讀全文
第一版的NativeBuffering([上篇]、[下篇])發布之后,我又對它作了多輪迭代,對性能作了較大的優化。比如確保所有類型的數據都是內存對齊的,內部采用了池化機器確保真正的“零內存分配”等。對于字典類型的數據成員,原來只是“表現得像個字段”,這次真正使用一段連續的內存構架了一個“哈希表”。我們知道對于每次.NET新版本的發布,原生的JSON序列化(System.Text.Json)的性能都作了相應的提升,本篇文章通過具體的性能測試比較NativeBuffering和它之間的性能差異。 閱讀全文
之前開發的一款基于OpenTelemetry的Tracing組件需要使用基于速率限制(Rate Limiting)的跟蹤采樣策略,本想使用現有的解決方案,比如System.Threading.RateLimiting命名空間下的RateLimiter。大體看了RateLimiter的三種實現(固定窗 閱讀全文
《.NET中的數組在內存中如何布局? 》介紹了一個.NET下針對數組對象的內存布局。既然我們知道了內存布局,我們自然可以按照這個布局規則創建一段字節序列來表示一個數組對象。 閱讀全文
總的來說,.NET的值類型和引用類型都映射一段連續的內存片段。就內存布局來說,引用類型有兩個獨特的存在,一個是字符串,另一個就是數組。今天我們來聊聊數組類型的內存布局。 閱讀全文
上文說到Unmanaged、BufferedBinary和BufferedString是NativeBuffering支持的三個基本數據類型,其實我們也可以說NativeBuffering只支持Unmanaged和IReadOnlyBufferedObject 閱讀全文
之前一個項目涉及到針對海量(千萬級)實時變化數據的計算,由于對性能要求非常高,我們不得不將參與計算的數據存放到內存中,并通過檢測數據存儲的變化實時更新內存的數據。存量的數據幾乎耗用了上百G的內存,再加上它們在每個時刻都在不斷地變化,所以每時每刻都無數的對象被創建出來(添加+修改),同時無數現有的對象被“廢棄”(刪除+修改)。這種情況針對GC的壓力可想而知,所以每當進行一次2代GC的時候,計算的耗時總會出現“抖動”。為了解決這類問題,幾天前嘗試著創建了一個名為NativeBuffering的框架 閱讀全文
作為構建.NET的標準,CLI Spec(ECMA-335)針對基元類型的對齊規則具有如下的描述。按照這個標準,我們是這么理解的:8字節的數據類型(int64、unsigned int64和float64)根據采用的機器指令架構選擇4字節或者8字節對其。進一步來說,它們在x86/x64機器上的對其字節分別為4字節和8字節,但實驗證明卻并非如此。 閱讀全文
毫無疑問,字符串是我們使用頻率最高的類型。但是如果我問大家一個問題:“一個字符串對象在內存中如何表示的?”,我相信絕大部分人回答不上來。我們今天就來討論這個問題。 閱讀全文
一個對象總是映射一塊連續的內存序列(不考慮對象之間的引用關系),如果我們知道了引用類型實例的內存布局,以及變量引用指向的確切的地址,我們不僅可以采用純“二進制”的方式在內存“繪制”一個指定引用類型的實例,還可以修改某個變量的“值”指向它 閱讀全文
非公開的類型或者方法被“隱藏”在程序集內部,本就不希望從外部訪問,但是有時候調用一個內部或者私有方法可能是唯一的“救命稻草”,這篇文章列出了幾種具體的實現方式。 閱讀全文
C#具有一個默認開啟的代碼分析規則:[CA1810]Initialize reference type static fields inline,推薦我們以內聯的方式初始化靜態字段,而不是將初始化放在靜態構造函數中。 閱讀全文
現代化的應用及服務的部署場景主要體現在集群化、微服務和容器化,這一切都建立在針對部署應用或者服務的健康檢查上。ASP.NET提供的健康檢查不僅可能確定目標應用或者服務的可用性,還具有健康報告發布功能。ASP.NET框架的健康檢查功能是通過HealthCheckMiddleware中間件完成的。我們不僅可以利用該中間件確定當前應用的可用性,還可以注冊相應的IHealthCheck對象來完成針對不同方面的健康檢查。 閱讀全文
實例方法和靜態方法有區別嗎?對于很多人來說,這是一個愚蠢的問題。因為我們都知道它們的區別,實例方法作用于某個具體的上下文對象,該上下文對象可以利用this關鍵字獲得;靜態方法則是定義在某個類型中,不存在上下文對象的概念。但是如果我們從函數的角度來看的話,不論是靜態方法還是實例方法都是一個用于處理輸入參數的操作,貌似又沒有什么區別。 閱讀全文
同源策略是所有瀏覽器都必須遵循的一項安全原則,它的存在決定了瀏覽器在默認情況下無法對跨域請求的資源做進一步處理。為了實現跨域資源的共享,W3C制定了CORS規范。ASP.NET利用CorsMiddleware中間件提供了針對CORS規范的實現 閱讀全文
《老生常談:值類型 V.S. 引用類型》中花了很大的篇幅介紹ref參數針對值類型和引用類型變量的傳遞。在C#中,除了方法的ref參數,我們還有很多使用ref關鍵字傳遞引用/地址的場景,本篇文章作一個簡單的總結。 一、參數 二、數組索引 三、方法 四、ref 結構體 五、ref 結構體字段 一、參數 閱讀全文