术语: CLR :Common Language Runtime 公共语言运行期,有多种不同编程语言使用的运行库 托管模块:Managed Module,一个标准的MS Window可移植执行体文件(32位PE32或64位PE32+) IL:Intermediate Language 中间语言,又叫托管代码(由CLR管理它的执行) 元数据:metadata,一系列特殊的数据表 程序集:Assembly,抽象的 JIT:just-in-time 即时编译,将IL编译成本地CPU指令(本地代码) FCL:Framework Class Library,Framework 类库 CTS:Common Type System,通用类型系统,描述了类型的定义及其行为方式 CLI:Common Language Infrastructure,公共语言基础结构,这是MS提交给ECMA的一个标准,由CTS和其他Framwork组件构成 CLS:Common Language Specfication,公共语言规范,详细规定了一个最小特性集 1.1 将源代码编译成托管模块 CLR编译过程: C#源码文件——C#编译器编译——托管模块(IL和元数据) 托管模块的各个部分: 1.PE32或PE32+头 标志了文件类型,GUI/CUI/DLL,文件生成时间,在32位还是64位上运行 2.CLR头 CLR版本,入口方法,模块元数据,资源,强名称 3.元数据 3种类型的表 4.IL代码 元数据包括: 1.描述了模块中定义的内容,比如类及其成员 2.指出了托管模块引用的内容,比如导入的类及其成员 3.清单manifest,描述了构成Assembly的文件,由Assembly中的文件实现的公共导出类型,与Assembly相关联的资源/数据文件 元数据总是嵌入到与代码相同的EXE/DLL中,始终与IL保持同步。
元数据用途: 1.消除了对头/库文件的依赖,直接从托管模块中读取 2.智能感知,从元数据中解析 3.代码验证,使用元数据确保代码只执行安全操作 4.正反序列化 5.垃圾收集器跟踪对象的生存期以及对象的类型 1.2 将托管模块合并成程序集 程序集:一个或多个托管模块/资源文件的逻辑分组,是最小的重用,安全性以及版本控制单元。 既可以生成但文件程序集,也可以生成多文件程序集,这由编译器工具决定。 CLR是和程序集一起工作的,而不是和托管模块 1.3 加载CLR CLRVer命令,查看机器上所有CLR版本 csc的 /plattform开关,决定生成什么样的程序集:AnyCPU,x86,x64,Itanium 1.4 执行Assembly代码 ILAsm命令,将IL编译成Assembly;ILDasm将Assembly编译成IL。 高级语言(C#)只是CLR的一个子集,IL则允许访问CLR的所有功能。 JITCompiler函数,又名JIT编译器(JITter) 在方法首次执行时,CLR检测出Main的代码引用的所有类型,于是CLR分配一个内部数据结构,用于管理对引用类型的访问。 在这个内部结构中,每个方法都有一条对应的纪录以及地址。 对此结构进行初始化时,CLR将每条纪录都设置为CLR内部包含的一个未文档化的函数,即 JITCompiler函数。 JITCompiler函数被调用时,找到相应方法的IL,编译成本地CPU指令,并保存到一个动态内存块中,将该内存地址存入内部结构中,最后JITCompiler函数会跳转到内存块中的代码,执行。 第二次执行该方法时,不需要再编译,直接执行内存块中的代码。 JIT将本地代码保存在动态内存中,一旦程序终止,本地代码会被丢弃。 csc命令有2个开关会影响代码的优化:/optimize ,/debug
注意,[assembly:CLSComplant(true)]要写在namespace外。 我定义了两个不同方法A和a,编译器会有警告,说这样的语法不兼容CLS;如果去掉[assembly:CLSComplant(true)]声明,那么不会有这个警告;如果将a方法改为private,则不会有警告。 中途我使用了ILDasm观察这个dll,发现两个方法A和a都存在于IL中,说明IL的语法范围也大于CLS。 在VB中,我添加了对此dll的引用:
发现,在c1.后面不会有A或a方法的智能感知,说明VB不能识别不符合CLS的语法。如果修改了dll中的a方法为private或者删除a方法,则在VB中可以智能感知到A方法。 可以得出结论,不符合CLS的语法,在另一种语言中是看不到的。 1.9 COM互操作 3种互操作情形: 1.托管代码可以调用DLL中包含的非托管函数,如Kernal32.dll,User32.dll 2.托管代码可以使用现成的COM组件 3.非托管代码可以使用托管类型(C#写的ActiveX控件或shell扩展)