參考組件

參考組件是特殊的組件型別,只包含代表程式庫公用 API 介面所需的最小中繼資料量。 其中包括在建置工具中參考組件時所有成員的宣告,但排除對私人成員的所有成員實作和宣告,這些私人成員的 API 合約沒有受到明顯影響。 相反地,一般組件稱為實作組件

無法載入參考組件以供執行,但可以使用與實作組件相同的方式來傳遞作為編譯器輸入。 參考組件通常會與特定平台或程式庫的軟體開發套件 (SDK) 一起散發。

使用參考組件可讓開發人員建置以特定程式庫版本為目標的程式,而不需要該版本的完整實作組件。 假設您的電腦上只有最新版本的程式庫,但是您想要建置以該程式庫舊版為目標的程式。 如果您直接針對實作組件進行編譯,您可能會不小心使用舊版中無法使用的 API 成員。 只有在目標電腦上測試程式時,您才會發現這個錯誤。 如果您針對舊版的參考組件進行編譯,將會立即收到編譯時期錯誤。

參考組件也可以代表合約,也就是一組未對應至具體實作組件的 API。 這類參考組件稱為合約組件,可用來以支援相同 API 集合的多個平台為目標。 例如,.NET Standard 提供合約組件 netstandard.dll,代表不同 .NET 平台之間共用的一組通用 API。 這些 API 的實作包含在不同平台上的不同組件中,例如 .NET Framework 上的 mscorlib.dll 或 .NET Core 上的 System.Private.CoreLib.dll。 以 .NET Standard 為目標的程式庫可以在支援 .NET Standard 的所有平台上執行。

正在使用參考組件

若要從專案使用特定 API,您必須將參考新增至其組件。 您可以將參考新增至實作組件或參考組件。 建議您一旦參考組件可用,就加以使用。 這麼做可確保您只使用目標版本中支援的 API 成員,專供 API 設計工具使用。 使用參考組件可確保您不會相依於實作詳細資料。

.NET Framework 程式庫的參考組件會與目標套件一起散發。 您可以下載獨立安裝程式,或在 Visual Studio 安裝程式中選取元件來取得。 如需詳細資訊,請參閱安裝適用於開發人員的 .NET Framework。 針對 .NET Core 和 .NET Standard,參考組件會視需要自動下載 (透過 NuGet) 並且參考。 針對 .NET Core 3.0 和更新版本,核心架構的參考組件位於 Microsoft.NETCore.App.Ref 套件中 (Microsoft.NETCore.App 套件會改為用於 3.0 之前的版本)。

當您使用 [新增參考] 對話方塊在 Visual Studio 中新增 .NET Framework 組件的參考時,您會從清單中選取組件,而 Visual Studio 會自動尋找對應至專案中所選取目標架構版本的參考組件。 這同樣適用於使用參考專案項目直接將參考新增至 MSBuild 專案:您只需要指定組件名稱,而不是完整的檔案路徑。 當您使用 -reference 編譯器選項 (在 C# 和在 Visual Basic) 或在 Roslyn API 中使用 Compilation.AddReferences 方法,在命令列中將這些參考新增至組件時,您必須手動指定正確目標平台版本的參考組件檔。 .NET Framework 參考組件檔位於 %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NET Framework 目錄中。 針對 .NET Core,您可以強制執行發佈作業,藉由將 PreserveCompilationContext 專案屬性設定為 true,將目標平台的參考組件複製到輸出目錄的 publish/refs 子目錄中。 然後,您可以將這些參考組件檔傳遞至編譯器。 使用來自 Microsoft.Extensions.DependencyModel 套件的 DependencyContext,可以協助找到其路徑。

因為不包含任何實作,所以無法載入參考組件以供執行。 嘗試這樣做會導致 System.BadImageFormatException。 如果您要檢查參考元件的內容,您可以將它載入 .NET Framework 中僅限反映的內容(使用 Assembly.ReflectionOnlyLoad 方法)或 MetadataLoadContext .NET 和 .NET Framework 中的 。

正在產生參考組件

當您的程式庫取用者需要針對許多不同版本的程式庫建置其程式時,為您的程式庫產生參考組件可能會很有用。 散發所有這些版本的實作組件可能因為其大小很大而不切實際。 參考組件的大小較小,並將其散發為程式庫 SDK 的一部分,可減少下載大小並節省磁碟空間。

如果是包含多個類別庫的大型解決方案,IDE 和建置工具也可以利用參考組件來減少建置時間。 通常,在增量建置案例中,專案會在變更任何輸入檔時重建,包括相依的組件。 每當程式設計人員變更任何成員的實作時,實作組件就會變更。 參考組件只會在其公用 API 受到影響時變更。 因此在某些情況下,使用參考組件作為輸入檔,而不是實作組件允許略過相依專案的建置。

您可以產生參考組件:

如果您想要散發具有 NuGet 套件的參考組件,您必須將其包含在套件目錄底下的 ref\ 子目錄中,而不是用於實作組件的 lib\ 子目錄。

參考組件結構

參考組件是相關概念的擴充,僅限中繼資料的組件。 僅中繼資料組件以單一的 throw null 主體取代其方法主體,但包含匿名型別以外的所有成員。 使用 throw null 主體的原因 (相對於沒有主體),是這樣 PEVerify 便可執行和傳遞 (因此驗證中繼資料的完整性)。

參考組件會進一步移除來自僅中繼資料組件的中繼資料 (私用成員):

  • 參考組件只有在 API 介面中所需項目的參考。 實際的組件可能有與特定實作相關的其他參考。 例如,class C { private void M() { dynamic d = 1; ... } } 的參考組件不參考 dynamic 所需的任何型別。
  • 如果移除它們不會明顯影響編譯的話,則會移除私用函式的成員 (方法、屬性和事件)。 如果沒有 InternalsVisibleTo 屬性,也會移除內部函式成員。

參考組件中的中繼資料會繼續保留下列資訊:

  • 所有型別,包括私人和巢狀型別。
  • 所有屬性,甚至是內部屬性。
  • 所有虛擬方法。
  • 明確介面實作。
  • 明確實作的屬性和事件,因為其存取子是虛擬的。
  • 結構的所有欄位。

參考組件包含組件層級的 ReferenceAssembly 屬性。 這個屬性可在來源中指定,然後編譯器就不需要合成。 因為這個屬性,執行階段會拒絕載入參考組件以供執行 (但可以載入僅限反映模式)。

確切的參考組件結構詳細資料取決於編譯器版本。 如果較新版本判定為不會影響公用 API 介面,則可以選擇排除更多中繼資料。

注意

本節中的資訊僅適用於從 C# 7.1 版或 Visual Basic 15.3 版開始,由 Roslyn 編譯器產生的參考組件。 .NET Framework 和 .NET Core 程式庫的參考組件結構在某些詳細資料中可能會有所不同,因為其使用自己的產生參考組件機制。 例如,其可能會有完全空白的方法主體,而不是 throw null 主體。 但是一般原則仍然適用:其沒有可用的方法實作,而且只包含從公用 API 觀點具有可觀察影響的成員中繼資料。

另請參閱