• 生成、打包应用程序及类型


    将类型生成到模块中


      本节讨论如何将源代码文件转换成可以部署的文件。先看下面这个简单的示例:

    1. 创建文本文件Program.txt,打开记事本键入如下代码

      public class Program
      {
          static void Main()
          {
              System.Console.WriteLine("Hello");
              System.Console.ReadLine(); 
          }
      }
    2. 将文件的后缀名修改为.cs
    3. 在命令行执行以下命令:

      C:WindowsMicrosoft.NETFramework64v4.0.30319csc.exe /out:Program.exe /t:exe /r:MSCorLib.dll Program.cs

      执行结果如下:

      命令说明:

      MSCorLib.dll是特殊文件,它包含所有核心类型。由于这些类型使用频繁,以至于C#编译器会自动引用MSCorLib.dll程序集,也就是说,上述命令中的/r:MSCorLib.dll可以省略。又因为/out:Program.exe和/t:exe开关是C#编译器的默认设定,所以上述命名可以继续简化为C:WindowsMicrosoft.NETFramework64v4.0.30319csc.exe Program.cs

    4. 步骤3中的命令执行完毕后,会在相应路径下生成可执行文件Program.exe,双击该可执行文件,结果如下:

    响应文件

      响应文件是包含一组编译器命令行开关的文本文件,执行csc.exe时,编译器打开响应文件,使用其中包含的所有开关。.NET Framework安装时会在%SystemRoot%Microsoft.NETFramework(64)vX.X.X目录中安装默认全局CSC.rsp文件(X.X.X是安装的.NET Framework版本号),全局CSC.rsp文件引用了列出的所有程序集,所以不必使用C#编译器的/reference开关显示引用这些程序集。



    元数据概述


      元数据是由几个表构成的二进制数据块。分别是定义表、引用表和清单表。编译器在编译源代码时,代码定义的任何项都会在定义表中创建一个记录。常用的元数据定义表如下:

    元数据定义表名称说明
    ModuleDef 包含对模块进行标识的一个记录项。该记录项包含模块文件名和扩展名,以及模块版本ID
    TypeDef 记录模块中定义的类型在。包含类型的名称、基类型、一些标志和索引,这些索引指向MethodDef、FieldDef、PropertyDef、EventDef中的成员
    MethodDef 记录模块中定义的方法
    FieldDef 记录模块中定义的字段
    ParamDef 记录模块中定义的参数
    PropertyDef 记录模块中定义的属性
    EventDef 记录模块中定义的事件

    此外,编译器还会检测源代码引用的类型、字段、方法、属性和事件,并创建相应的引用表,它们记录了引用的内容。

    引用表名称说明
    AssemblyRef 记录模块引用的每个程序集
    ModuleRef 记录该模块所引用的类型的每个PE模块
    TypeRef 记录模块引用的每个类型
    MemberRef 记录模块引用的每个成员

    要查看元数据的相关内容,可以使用微软提供的IL反汇编工具ILDasm.exe检查托管PE文件中的元数据,所在目录:

    C:Program Files (x86)Microsoft SDKsWindowsv10.0AinNETFX 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:WindowsMicrosoft.NETFramework64v4.0.30319csc.exe /t:module UncommonTypes.cs

    3. 将CommonTypes编译到另一个模块,该模块将成为程序集清单的宿主,因为这些类型会经常使用。生成文件MultiFileLibrary.dll

      C:WindowsMicrosoft.NETFramework64v4.0.30319csc.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
     
     
  • 相关阅读:
    使用InternalsVisibleTo给assembly添加“友元assembly”
    从.snk文件导出密钥
    解决Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COER
    MySQL max_allowed_packet设置及问题
    MySQL导入sql脚本错误:2006
    执行nova-manage db sync时出错,提示’Specified key was too long; max key length is 1000 bytes’
    MySQL编码latin1转utf8
    微软为何选择在 Github 上开源 .NET 核心?
    In House打包流程
    GetBuiltProjectOutputRecursive error running Xamarin Forms iOS on Visual Studio
  • 原文地址:https://www.cnblogs.com/wenJiaQi/p/7309440.html
Copyright © 2020-2023  润新知