.NET科普:.NET簡史、.NET Standard以及C#和.NET Framework之間的關係

来源:https://www.cnblogs.com/daxnet/p/18299758
-Advertisement-
Play Games

最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...


最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。

首先,你沒看錯,.NET是跨平臺的,可以在Windows、Linux和MacOS以及它們的各個發行版上運行,不僅如此,從2022年4月28日開始,.NET開源社區正式支持國產龍芯晶元龍架構(LoongArch),這使得.NET在國家信創這一領域又邁出了一大步。咦?.NET跨平臺這事情我知道呀,為何要特別提起呢?因為真的有很多人不知道,而且不乏各種短視頻平臺里出現的各種技術專家和技術大咖,紛紛表示.NET只能在Windows上運行,跨平臺困難,落地和部署困難。

其次,.NET的成功案例有很多,大家都知道,.NET和C#會用在游戲開發、工控領域、老系統維護等項目和場景中,卻並不瞭解其實下麵這些也都是.NET的成功案例,或者有著.NET的影子:

  1. Stackoverflow - 全球最大技術問答網站
  2. Microsoft Azure - 微軟雲平臺
  3. 博客園 - 就是本站
  4. Microsoft Bing - 微軟搜索引擎
  5. Office 365
  6. Azure DevOps
  7. GoDaddy
  8. Trello
  9. DocuSign
  10. Github的部分後端服務 - 說明一下,Github主要是Ruby on Rails實現的,可是還有短視頻博主說Ruby語言快死了

在上面的列表中,有些可能你還不認識,剩下的認識的大部分都是微軟自己的產品,你會說.NET只有微軟自己用,但不管是誰用,這些站點和應用都是超大規模級別的,說明使用.NET來構建超大規模級別的大型應用是完全沒有問題的:容器化、雲原生、微服務、Serverless,.NET都可以勝任;AI時代,ML.NET、Semantic Kernel、LLamaSharp、Cognitive Services等等.NET原生框架和開發SDK,在微軟Azure OpenAI Services的加持下,為.NET在AI領域發力提供了更多的機會。

此外,.NET是開源的,.NET的各個部分通過不同的Repository維護在Github上,這些倉儲基本上都是以MIT和Apache 2的許可協議進行開源,由微軟員工作為主要貢獻者,因此,在開源的同時,又保證了倉儲的持續更新維護和提交代碼的質量。不僅如此,.NET Foundation還收納了不少知名開源項目,這對完善整個.NET生態起到了非常積極的作用。

那這裡的.NET是指.NET Framework嗎?算是,但也不完全是。之前為大家熟知的那個只能在Windows下運行的版本,稱為.NET Framework,自2016年開始,微軟發佈跨平臺版本的.NET框架時,它作為經典.NET Framework的跨平臺版本,被稱之為.NET Core,.NET Core延續到3.1版之後,被改名為.NET 5,然後就是後來的6、7、8、9等各個版本。對於這部分內容,我後面會介紹,但我想在介紹更多詳細信息之前,先簡單地回顧一下.NET的歷史。

.NET極簡史:從Visual J++開始

大家都知道,剛剛退休的Java之父詹姆斯·高斯林曾經在1991年就開始參與Java語言的構建,然後Sun Microsystems公司於1996年發佈了Java 1.0版本,但很少有人知道,微軟在同年10月份發佈了自己的Java語言:Visual J++。Visual J++開發的程式基於微軟自研的MSJVM運行,雖然J++遵循Java語言規範,但微軟並沒有選擇完全根據Sun公司的Java規範來設計自己的JVM,於是,MSJVM實際上並不完全支持Sun Java的所有能力,包括Java RMI和JNI。而另一方面,微軟還在Visual J++中加入了一些自己的設計,比如通過回調函數和委托來實現事件處理,這就使得Visual J++變得更像另一種新的編程語言。不僅如此,Visual J++在訪問系統資源方面,也不遵循Sun Java SDK規範,而是通過自己定義的J/Direct介面來讓代碼直接訪問操作系統層面的API,於是,Visual J++在某些方面性能要大大優於Sun Java(很是懷疑這個J/Direct就是後來的P/Invoke)。從技術角度,使用了這些特殊功能的J++應用程式其實無法在Sun Java JVM上運行,不過當時也有不少開源項目,比如Kaffe項目,它們可以使J++應用程式無需移植即可直接在這些開源的JVM上運行。但這些開源項目也最終沒有被廣泛應用。

一開始的時候,Sun公司願意在Java語言上與微軟合作,而由於Visual J++里的各種騷功能和騷設計打破了Sun Java規範,以至於MSJVM未能通過Sun公司的合規性測試,於是,在Sun公司的起訴下,微軟逐漸停止了Visual J++的研發。不過,在這個過程中,微軟積累了豐富的技術和經驗,這些技術和經驗逐漸演化成後來的.NET平臺和Visual J#(一種可以運行在.NET Framework上的Java編程語言,註意:是編程語言,就是用Java的語法寫.NET Framework的應用程式)。Visual J#是Visual J++的續作,目的是能夠讓原來的Visual J++開發人員可以平滑地遷移到.NET平臺上。

之後就是2002年4月15日發佈的.NET Framework 1.0和Visual Studio.NET 2002(註意是Visual Studio.NET,不是Visual Studio,從Visual Studio 2005開始,名字里去掉了.NET字樣),它可以安裝並運行在Windows NT 4.0 SP6、Windows 98、Windows 98 SE、Windows ME、Windows 2000和Windows XP系統上。當年我正好讀大三,記得資料庫這門課的課程設計,就是用Visual Studio.NET 2002做的。由於操作系統可以是32或者64位的,屬於不同的CPU架構,因此,從這個層面也可以說.NET是跨平臺的:在Windows操作系統下跨平臺。說起跨平臺,雖然一開始由於市場策略、技術實現、開源生態等等因素,微軟最終選擇讓.NET只在Windows下運行,但同時也力求將各種設計通過ISO和ECMA進行標準化,這為後續社區版跨平臺.NET Framework:Mono Project、Xamarin以及.NET Core的出現,打下了堅實的基礎。

值得一提的是,由於CLI標準化的存在,使得任何編程語言,只要符合相關規範,都可以在.NET上運行(這裡我就不區分跨平臺.NET還是經典.NET Framework了,單說編程語言這部分內容,兩者原理是一樣的),於是,你可能會看到有人使用以下語言來開發.NET應用程式:

  • Visual C#:不用說,.NET語言中的一等公民,為什麼叫C#?因為它比C++多兩個+號,四個+號兩個一行,就拼成了#,足以明微軟之志:C#比C++更發達。C#語言由編程大神安德爾斯·海爾斯伯格設計,不認識他?他基於PASCAL語法,編寫了當時編譯效率最高的Borland Turbo Pascal編譯器,最終成就了Borland Delphi,他還是Typescript的作者。啥也別說,給賞飯吃的大神三鞠躬
  • Visual Basic.NET(VB.NET):不用說,微軟系編程語言中資歷最老的,比爾蓋茨就是靠BASIC語言起家
  • F#:微軟自研函數式編程語言,國內用的不多,國外狂熱分子不少
  • C++/CLI:微軟自研托管C++語言,運行在.NET CLR上,它可以直接鏈接原生C++的庫,從而在.NET項目中提供C++的互操作性(interoperability)
  • Powershell:微軟自研的跨平臺的自動化配置管理工具/框架,它對於結構化數據(比如JSON、XML等)的處理、RESTful API的訪問以及處理對象模型等方面做了很好的優化。國內應用不多,但國外社區非常活躍
  • IronPython:一個在.NET上運行的Python的開源版本,它可以同時使用Python和.NET的開發庫,在一些專業性的產品上有一定應用,比如全球領先的BI軟體Spotfire就提供IronPython的運行時(Runtime),並允許IronPython腳本運行在服務端。IronPython最新更新是在2023年7月
  • IronRuby:跟IronPython類似,是Ruby語言的.NET實現,但是在10多年前就已經停更了
  • Visual J#:已經停產,更沒人用了,列在這裡主要就是為了說明,即使是Java編程語言,也是可以支持.NET的
  • Delphi 8及之後的版本,有對.NET Framework支持的功能

從2002年4月15日到2022年8月9日這20年時間,.NET Framework經歷了大大小小17個版本,功能也在不斷的增強,在2016年隨著.NET Standard的引入,從.NET Framework 4.5開始,不同版本的.NET Framework也被歸屬到對應版本的.NET Standard之下,而發佈於2019年4月18日的.NET Framework 4.8,也成為了經典.NET Framework的最後一個版本(雖然2022年8月9日發佈了.NET Framework 4.8.1,但並不是一個主版本)。

後續版本的.NET被稱為.NET 5,從版本號上可以看到,.NET 5可以看成是.NET Framework 4.8的延續,它去掉了“Framework”字樣,以示與之前經典.NET Framework的區別,.NET 5及後續版本都是跨平臺的,現在回看這段歷史可以發現,之前的.NET Core 1.0到3.1其實都是.NET跨平臺歷程的中間版本,這些版本存在的價值,就是讓.NET開發人員和用.NET Framework開發的項目可以通過這些.NET Core的版本,能夠無縫地、逐步地過渡到跨平臺的、現代化的.NET上。不得不佩服微軟在.NET跨平臺這方面無論在市場戰略上,還是技術戰術上,都表現得非常出色。

.NET歷史就介紹這麼點,瞭解這些基本也就夠了,接下來我會逐步從技術角度,來介紹一些與.NET相關的新概念。

.NET跨平臺與.NET Standard

可以這樣理解:.NET Standard是.NET跨平臺的基礎。.NET Standard其實就是一套.NET下的API規範,它的第一個版本與2016年的.NET Core 1.0同時發佈,每一個版本的.NET Standard都規定了實現這一版本規範的不同的.NET實現應該包含哪些API。更具體些:為了跨Linux、MacOS、Windows、iOS、Android等多個平臺,.NET會針對這些平臺提供不同的實現,這些實現包括:.NET Core、.NET Framework、Xamarin套件(iOS、Mac和Andriod)、用於游戲開發的Unity下的.NET等等,如果這些實現能夠遵循某個版本的API標準,那麼,基於這個版本的API標準所開發的應用程式,就可以運行於這些不同平臺上,而這套API標準就是.NET Standard。另一方面,如果希望開發出來的類庫和組件能夠被不同平臺的應用程式使用,那麼,只需要指定這個類庫和組件所基於的.NET Standard版本即可。

然而,最開始的.NET Framework並不能跨平臺,微軟為了逐步實現.NET跨平臺這個目標,先後發佈了從1.0到2.1一共9個版本的.NET Standard,每個.NET Standard版本下,都增加一部分.NET API的支持,比如,.NET Standard 1.0僅支持37118個API中的7949個,.NET Standard 2.0支持37118個API中的32638個,而最新的.NET Standard 2.1則支持所有37118個API。因此,在不同版本的.NET Standard下,就會有對應版本的.NET實現對其進行支持。比如對於.NET Standard 2.0,經典的.NET Framework需要4.6.1及以上的版本才支持.NET Standard 2.0,因為這些版本實現了.NET Standard 2.0中所定義的那32638個API。於是,使用.NET Standard 2.0開發的類庫,就可以被.NET Framework 4.6.1所引用。

演練:在不同的.NET項目中使用.NET Standard 2.0類庫

在Visual Studio 2022中,新建一個.NET Standard 2.0的Class Library:

然後加入一個類:

再新建一個經典.NET Framework 4.6.1的Console Application:

然後直接引用前面的ClassLibraryNetStandard20類庫並寫代碼調用裡面的函數,可以看到,程式可以正常運行:

當然,這個ClassLibraryNetStandard20也可以被一個.NET 8的應用程式調用:

打開這個ClassLibraryNetStandard20項目的輸出目錄,可以看到,編譯出來的程式集被放在了Debug\netstandard2.0目錄下:

但是,如果我們新建一個.NET Standard 2.1的Class Library,則無法被.NET Framework 4.6.1的項目引用,此時會報錯:

因為.NET Framework 4.6.1沒有實現.NET Standard 2.1,換句話說,.NET Standard 2.1中的有些API在.NET Framework 4.6.1中並沒有實現,那麼基於.NET Standard 2.1開發出來的類庫自然也不能被.NET Framework 4.6.1的項目所引用。經典.NET Framework的最後一個版本4.8.1僅實現了.NET Standard 2.0,因此,如果你打算開發一個既可以被經典.NET Framework項目使用,又可以被跨平臺.NET(曾經的.NET Core,現在的.NET 5+)項目使用的話,你需要將你的類庫定向(targeting)到.NET Standard 2.0,或者使用多目標框架(Multi-targeting)。

在【這個頁面】中,有一張表,展示了.NET Standard各個版本與不同的.NET實現的版本之間的對應關係,可以通過下拉框來選擇不同的.NET Standard版本來查看不同的.NET實現的哪些版本與之對應。理論如此,但是在真正實踐的過程中,有些具體的問題是需要特殊處理的。比如:.NET Framework 4.7是支持.NET Standard 2.0的,但是,.NET Framework 4.7發佈於2017年4月,而.NET Standard 2.0則晚於.NET Framework 4.7發佈(2017年8月),那麼如何讓一個已經發佈的.NET Framework版本支持新的.NET Standard呢?解決方案就是使用NuGet Package,將.NET Framework中未實現的.NET Standard API以NuGet Package的形式引入,從而彌補這個差異。因此你會發現,對於.NET Framework 4.7.1及其以前版本的.NET項目,如果需要引用一個由.NET Standard 2.0實現的類庫的話,就需要額外引用NETStandard.Library這個Meta Package,這個Meta Package中包含了不同版本.NET項目所需依賴的Assembly的版本信息。另外,Visual Studio在處理這個事情上也有差異:

  • Visual Studio 2017 15.3之前的版本需要在IDE中顯式引用這個Meta Package
  • Visual Studio 2017 15.3開始,不再需要在IDE中顯式引用這個Meta Package,也就是說,在新建的.NET Framework 4.7.1及以前版本的項目上引用.NET Standard 2.0,不再需要額外去引用NETStandard.Library,Visual Studio會自動幫你完成這個工作。當然,這並不表示你的項目就不需要NETStandard.Library了,只是在IDE的操作上比以前更加簡單了

在編譯出來的結果上也存在差異,下麵左圖是一個.NET Framework 4.7的項目引用了一個.NET Standard 2.0的項目後的編譯輸出,右圖是.NET Framework 4.8.1的項目引用了.NET Standard 2.0項目後的編譯輸出,可以看到,4.7的項目編譯後,會在編譯路徑下生成一堆System DLL,外加一個netstandard.dll,而4.8.1的項目編譯生成路徑下就非常乾凈,因為.NET Framework 4.8.1已經自帶了這些DLL了:

多目標框架(Multi-targeting)

儘管.NET Standard提供了不同.NET實現(.NET Framework、.NET Core和Xamarin等)之間統一的API規範,但在有些場景下,仍然希望能夠充分利用不同平臺的特性和性能優化,或者需要支持特定平臺的功能,此時僅將項目定向到.NET Standard已經不能滿足需求。對於這種場景,.NET允許開發麵向多目標框架的類庫,一方面可以通過條件編譯指令來使用特定平臺的API,另一方面也可以為類庫的調用方提供不同平臺的支持。

比如,在C#項目文件(.csproj文件)中,使用下麵的方式,讓類庫同時支持.NET Standard 2.1項目和.NET Framework 4.8的項目:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.1;net4.8</TargetFrameworks>
    <Nullable>enable</Nullable>
    <LangVersion>8.0</LangVersion>
  </PropertyGroup>

</Project>

註意上面的TargetFrameworks標記,在這個XML標記下,列出了該類庫所支持的.NET Standard/.NET Framework的版本,它在編譯之後,會產生兩個輸出文件夾,其中包含了支持不同版本.NET的程式集:

另一個需要註意的地方是,在上面的csproj文件定義中,指定了所使用的C#版本為8.0,這是因為“可空引用類型”(Nullable Reference Types)是在C# 8.0中引入的,而如果將代碼同時定向到.NET Framework 4.8,那麼就無法支持可空引用類型,因為.NET Framework 4.8所支持的最高的C#版本為C# 7.3。有關.NET與C#版本之間的關係,後文我會介紹。

一個使用“多目標框架”的非常著名的開源框架就是log4net。log4net是一個古老的.NET下的日誌輸出工具,它一開始是log4j的.NET移植版本,所以,老版本的log4net使用了很多經典.NET Framework特有的API,比如System.Configuration命名空間下的基於XML的框架配置代碼。隨著.NET Core和跨平臺.NET的發佈,log4net也逐步提供了對.NET Standard 1.3和.NET Standard 2.0的支持,所以,現在的.NET 5/6/7/8項目都可以直接引用log4net用作日誌輸出。在log4net的官方代碼庫中,可以學習到它是如何實現多目標框架的。

事實上從.NET 5開始,.NET真正實現了跨平臺,.NET Standard也基本完成了它的使命,但.NET Standard並不會退出歷史舞臺,微軟會繼續對其進行維護。

至此,與.NET跨平臺和.NET Standard相關的內容就差不多介紹完了,當然還有部分細節和一些歷史遺留問題的處理方式相關內容(比如Portable Class Library,PCLs),這裡就不再贅述了,否則篇幅太長,hold不住啊。接下來我們聊聊C#和.NET Framework之間的關係吧。

C#語言特性與.NET Framework

如果你是C#語言的初學者,那麼你一定會產生一個疑問:intSystem.Int32有什麼區別?在C#中到底是使用int,還是用System.Int32?其實,C#中的int等價於System.Int32,也就是說,你既可以使用int這個C#關鍵字來定義一個32位有符號整數類型的變數,也可以使用System.Int32這個.NET類型來定義一個32位有符號整數類型的變數。官方文檔上說intSystem.Int32別名,但也可以理解為,int是C#能夠支持32位有符號整數類型的語言特性

由此可以得出一個結論:C#的語言特性是需要.NET Framework(或者.NET)支持的(有些高級的語言特性甚至需要不同版本的.NET CLR支持),但兩者的版本之間也不一定需要有嚴格的對應關係。C#語言特性本質上是通過C#編譯器實現的,只要編譯輸出的MSIL代碼能夠在.NET Framework(或者.NET)上運行起來,那麼這些語言特性就可以被該版本的.NET Framework所支持。下麵請看一個具體的案例。

演練:在.NET Framework 4.6.1的項目中使用C# 9.0的新特性

現在我們嘗試在一個.NET Framework 4.6.1(發佈於2015年11月)的項目中,使用C# 9.0(發佈於2020年11月)的新特性。首先新建一個.NET Framework 4.6.1的Console Application:

然後,修改csproj文件,將C#語言版本升級到C# 9.0:

然後,使用C# 9.0中“關係型模式匹配”新特性編寫一段代碼:

然後直接運行,可以看到,程式是可以正常編譯執行的:

那麼,是不是所有的C# 9.0的新特性,都可以在.NET Framework 4.6.1中使用呢?答案是否定的,就要看C# 9.0的編譯器是否可以生成能夠被該版本.NET Framework所支持的代碼,或者說,C#編譯器所生成的代碼中依賴的那些類型,是否在該版本的.NET Framework下支持。舉個例子,同樣是C# 9.0的新特性,僅限Init的資源庫新特性則無法直接在一個.NET Framework 4.6.1的項目中使用,編譯器提示:Predefined type 'System.Runtime.CompilerServices.IsExternalInit' is not defined or imported

原因是,C# 9.0編譯器在編譯帶有這個新語法特性的代碼時,需要檢查.NET下是否包含IsExternalInit類型,如果該類型存在,則允許使用該語法特性,而該類型在.NET Framework 4.6.1中不存在。因此,解決這個問題,既可以自己在項目中寫一個空的IsExternalInit類型,或者引用一個第三方的IsExternalInit NuGet Package。之後就可以正常編譯運行代碼了:

請註意:經典.NET Framework最高支持到C# 7.3,C# 8.0是專門面向.NET Core的第一個主要C#版本,它的一些新功能依賴於新的Core CLR的相關功能。【這篇官方文檔】詳細列舉了C#語言的發展歷史以及各個版本的新功能,下麵這張表格列舉了不同.NET版本下,創建新項目時所使用的預設的C#語言版本(參考官方文檔):

總結

本文先從介紹.NET歷史開始,引出跨平臺的相關話題,進而介紹了.NET Standard、Multi-targeting以及C#版本與.NET Framework之間的關係,文章所引用的外部文檔全都以超鏈接的形式嵌在文章之中,就不額外逐個列出。這些都不是最新內容,只是儘可能地做個總結,希望能夠幫到平時需要的朋友,同時也對.NET相關的概念和知識掃掃盲,讓更多的朋友瞭解.NET和C#這一優秀的框架和編程語言。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • AutoFixture是一個.NET庫,旨在簡化單元測試中的數據設置過程。通過自動生成測試數據,它幫助開發者減少測試代碼的編寫量,使得單元測試更加簡潔、易讀和易維護。AutoFixture可以用於任何.NET測試框架,如xUnit、NUnit或MSTest。 預設情況下AutoFixture生成的字 ...
  • 閱讀了 https://devblogs.microsoft.com/dotnet/configureawait-faq/,感覺其對於 .NET 非同步編程有非常有意義的指導,對於進一步學習和理解 .NET 非同步編程非常友邦做,所以進行翻譯以供參考學習。 七年多前,.NET 在語言和庫中加入了 asy ...
  • 前置 連接概述 連接是由兩個點之間創建的。Source和Target依賴屬性是Point類型,通常綁定到連接器的Anchor點。 基本連接 庫中所有連接的基類是BaseConnection,它派生自Shape。在創建自定義連接時,可以不受任何限值地從BaseConnection派生。 它公開了兩個命 ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...