生成、打包應用程序及類型

將類型生成到模塊中


  本節討論如何將源代碼文件轉換成能夠部署的文件。先看下面這個簡單的示例:編程

  1. 建立文本文件Program.txt,打開記事本鍵入以下代碼編程語言

    public class Program { static void Main() { System.Console.WriteLine("Hello"); System.Console.ReadLine(); } }
  2. 將文件的後綴名修改成.cs
  3. 在命令行執行如下命令:工具

    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:Program.exe /t:exe /r:MSCorLib.dll Program.cs

    執行結果以下:post

    命令說明:
    ui

    MSCorLib.dll是特殊文件,它包含全部核心類型。因爲這些類型使用頻繁,以致於C#編譯器會自動引用MSCorLib.dll程序集,也就是說,上述命令中的/r:MSCorLib.dll能夠省略。又由於/out:Program.exe和/t:exe開關是C#編譯器的默認設定,因此上述命名能夠繼續簡化爲C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe Program.csspa

  4. 步驟3中的命令執行完畢後,會在相應路徑下生成可執行文件Program.exe,雙擊該可執行文件,結果以下:.net

響應文件

  響應文件是包含一組編譯器命令行開關的文本文件,執行csc.exe時,編譯器打開響應文件,使用其中包含的全部開關。.NET Framework安裝時會在%SystemRoot%\Microsoft.NET\Framework(64)\vX.X.X目錄中安裝默認全局CSC.rsp文件(X.X.X是安裝的.NET Framework版本號),全局CSC.rsp文件引用了列出的全部程序集,因此沒必要使用C#編譯器的/reference開關顯示引用這些程序集。命令行



元數據概述


  元數據是由幾個表構成的二進制數據塊。分別是定義表、引用表和清單表。編譯器在編譯源代碼時,代碼定義的任何項都會在定義表中建立一個記錄。經常使用的元數據定義表以下:code

元數據定義表名稱 說明
ModuleDef 包含對模塊進行標識的一個記錄項。該記錄項包含模塊文件名和擴展名,以及模塊版本ID
TypeDef 記錄模塊中定義的類型在。包含類型的名稱、基類型、一些標誌和索引,這些索引指向MethodDef、FieldDef、PropertyDef、EventDef中的成員
MethodDef 記錄模塊中定義的方法
FieldDef 記錄模塊中定義的字段
ParamDef 記錄模塊中定義的參數
PropertyDef 記錄模塊中定義的屬性
EventDef 記錄模塊中定義的事件

此外,編譯器還會檢測源代碼引用的類型、字段、方法、屬性和事件,並建立相應的引用表,它們記錄了引用的內容。regexp

引用表名稱 說明
AssemblyRef 記錄模塊引用的每一個程序集
ModuleRef 記錄該模塊所引用的類型的每一個PE模塊
TypeRef 記錄模塊引用的每一個類型
MemberRef 記錄模塊引用的每一個成員

要查看元數據的相關內容,可使用微軟提供的IL反彙編工具ILDasm.exe檢查託管PE文件中的元數據,所在目錄:

C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools

使用ILDasm.exe打開上一節中的Program.exe程序集,選擇視圖|元信息|顯示!,隨後會顯示以下信息:

從元信息文件中咱們大體能夠看出Program.exe中包含名爲Program的TypeDef,這是一個公共類,從System.Object類派生,Program類型還定義了兩個方法:Main和.ctor(構造器)。

將模塊合併成程序集


  程序集是一個或多個類型定義文件及資源文件的集合。程序集中包含一個清單文件,主要包含做爲程序集組成部分的文件名稱、程序集版本、語言文化等描述性內容。CLR操做程序集,首先加載包含清單元數據表的文件,在根據清單來獲取程序集中的其餘文件的名稱。

爲何要引入程序集的概念?

由於使用程序集,可重用類型的邏輯表示與物理表示能夠分開。

使用多文件程序集的理由:

  • 不一樣的類型用不一樣的文件,使文件能以「增量」方式下載(將經常使用類型和不經常使用類型分開)。
  • 可在程序集中添加資源或數據文件。
  • 程序集包含的各個類型能夠用不一樣的編程語言來實現。

清單元數據表簡介:

清單元數據表名稱 說明
AssemblyRef 主要包含程序集名稱、版本、語言文化等內容
FileDef 記錄程序集中每一個PE文件和資源文件,若程序集只包含模塊自己,不包含其餘模塊和資源文件,FileDef表將無數據
ManifestResourceDef 記錄程序集中包含的每一個資源的名稱、標誌以及FileDef表中的一個索引
ExportedTpyesDef 記錄從程序集的全部PE模塊中導出的每一個public類型

下面,咱們將經過一個示例來講明如何生成多文件程序集。

  1. 首先準備兩個源代碼文件

    • CommonTypes.cs

      public class CommonTypes { public static void Main() { System.Console.WriteLine("Hello,This is CommonTypes"); System.Console.ReadLine(); } }
    • UncommonTypes.cs

      public class UncommonTypes { public static void Main() { System.Console.WriteLine("Hello,This is UncommonTypes"); System.Console.ReadLine(); } }
  2. 將UncommonTypes編譯到一個單獨的模塊中,生成文件UncommonTypes.netmodule

    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /t:module UncommonTypes.cs

  3. 將CommonTypes編譯到另外一個模塊,該模塊將成爲程序集清單的宿主,由於這些類型會常常使用。生成文件MultiFileLibrary.dll

    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:MultiFileLibrary.dll /t:library /addmodule:UncommonTypes.netmodule CommonTypes.cs

  4. 使用ILDasm.exe工具檢查元數據清單表,以下圖可知程序集文件確實包含了對UncommonTypes.netmodule文件類型的引用。

當有項目引用MultiFileLibrary.dll時,編譯器會在搜索外部類型時加載MultiFileLibrary.dll以及FileDef表中列出的全部文件,也就是說,若是刪除UncommonTypes.netmodule文件,編譯時會報錯



程序集版本資源信息


  CSC.exe生成PE文件程序集時,會在PE文件中嵌入標準的Win32版本資源。可查看文件屬性來檢查該資源。

版本號格式說明

版本號格式 major(主版本號) minor(次版本號) build(內部版本號) revision(修訂號)
示例 2 5 719 2
相關文章
相關標籤/搜索