Chapter 2
1. CLR程序存在于模块中(module)中。一个CLR模块是一个字节流,储存在一个文件(本地或远程服务器)。
2. CLR模块采用WinNT的PE(Portable Executable)/COFF(Common Object File Format)格式的扩展版。CLR模块也是有效的Win32模块,可以通过LoadLibrary系统调用加载。CLR模块用到的PE/COFF的功能极少,大部分内容是使用PE/COFF文件的.text部分。
3. CLR模块包括代码、元数据和资源。代码使用CIL(Common Intermediate Language)格式存放(个人理解:这个和MSIL或者IL是一个东西)。模块的元数据描述了模块中定义的类型,包含名字、继承关系、方法签名和依赖关系等。模块的资源由静态的只读数据组成(字符串、位图等)。
4. (/t:exe、/t:winexe、/t:library、/t:module)module产生的是“未加工”的模块(.netmodule)。/t:library编译产生的模块(.dll)包含元数据。/t:exe生成控制台程序、/t:winexe产生Win程序。
5. 起点为四种形式之一:static void Main(){}、static void Main(string[] argv){}、static void Main(){return 0}、static void Main(string[] argv){return 0}。是否有public无所谓,一个程序不可有多个入口,多个Main函数需要在编译时使用/main开关。
6. 程序集(assembly)为一个或多个模块的逻辑集合。程序集通过独立于位置的名字进行引用。这个名字必须翻译为文件系统中或Internet上的物理路径,最终指向一个或多个包含类型定义、代码以及资源的模块。
7. “多模块”的作用就是把“常用”和“不常用”的代码加载区分开来(可以在运行时做到“要什么下载什么”),可以作到使用一种语言写底层,一种语言写界面。
8. 一个模块往往只属于一个程序集,如果需要违反,那么会将这个公用模块产生两个不用的拷贝。
9. 模块依赖于来自其他程序集的类型(至少有mscorlib.dll里的),每个模块都有一个程序集名字列表,然后CLR负责在运行时将这些程序集的名字转换成模块的路径名。
10. 每个程序集有一个程序集清单(assembly manifest),这是元数据的一部分,相当于附加类型定义和代码的附属文件目录。
11. 含有程序集清单的模块首先被CLR加载,然后根据这个清单的内容加载其余不含清单的模块。
12. 引用别的模块使用/addmodule开关,引用别的程序集使用/r开关。
13. 含有程序集清单的模块将包含外部引用程序集的主要列表。列表由程序集中每个模块的依赖关系组成,这样通过加载一个文件就能找到程序集所有的依赖关系。
14. internal导致只对同一程序集的模块可用;public导致所有的代码都可用;private只有该类型的方法才可用;protected使派生类的方法等也能访问该成员;protected和internal可以一起用。
15. 命名空间(namespace)+类名。
16. 每个程序集采用四部分(four-part)名字,作为唯一的标识。这四部分为名称、文化、开发人员、组件版本。这些名字被放在程序集清单里,在加载时,CLR使用四部程序集名字找到正确的组件。
17. 每个程序集的名字都有一个版本号:Major.Minor.Build.Revision,如果没有显式设定这个版本号,那么就是 0.0.0 .0。System.Reflection.AssemblyVersion能接受各种字符串格式(1.2.d.s等)。
18. CultureInfo特性标识着组件开发所用到的语言和国家代码(语言环境)。含有CultureInfo特性的程序集不能包括代码,必须是“纯资源”的程序集(resource-only)。含代码的程序集是文化无关的(culture-neutral)。
19. 程序集名字包含一个“公钥”(public key),标识组件的开发人员。可以选择使用8位的或者128位的公钥标记,这样就可以标记着相同文件名的不同程序集。
20. 有时候必须手动引用程序集。CLR定义了一个标准格式,用于将程序集的四部分名字编写字符串。这个格式被称为程序集的显示名字(display name):Name, Virsion=X.X.X.X, Culture=[xx-XX | Neutral], PublicKeyToken=[XXXXXXXXXXXXX | Null]。Culture为Neutral表示程序集没有文化限制,PublicKeyToken为null表示不带公钥。简单省略一个部分的限定名字表示允许匹配任何Culture或PublicKeyToken。
21. 一般来说,应该避免使用程序集的部分限定名,否则CLR可能会以非预期的方式运行。可以在配置文件里写全名,然后使用部分名在程序中调用(Assembly assm = Assembly.Load(“XXXX”))。PartialName(上面的XXXX)必须存在于配置文件的PartialName中
22. CLR会尽量少加载不需要的模块,当确实使用了才会加载。这样减少了初始化时间,也减少了运行程序所消耗的资源。CLR加载是由基于类型的JIT编译器触发的,JIT将方法体的CIL编译成机器码时,要访问的局部变量,参数等数据类型会被一起加载。
23. 如果不要CLR屡次的加载模块可以有两种做法:一是定义一些静态字段。二是用手动显式加载。
24. 如果要显式的和程序集交互,需要使用System.Reflection.Assembly的LoadFrom方法,它可以是本地的一个文件,也可以是“file://...”,如果是从非“file://...”的URL中调用,则需要Web Permission,这个模块被加载时会被首先下载到缓存里。
25. 尽管通过位置加载程序集很有意思,但是大多数程序集是通过程序集解析器(assembly resolver)按名字加载的。方法是System.Reflection.Assembly的Load方法,涉及到所在目录,版本控制和一些其他配置细节的问题。
26. 程序集解析器首先采用的是有效的版本策略(version policy),然后可能会加载所需程序集的替代版本(不同版本的程序集为不同程序集,但是程序集映射的时候必须同名)。版本策略只能应用于四部分名完全限定的程序集,如果程序集名字是部分限定的(比如缺少公钥标记,版本或文化)那么就不能用版本策略了(直接使用LoadFrom方法由于指定的是文件,所以就没有什么版本策略的问题了)。
27. 版本策略可以通过配置文件决定,计算机范围(machine-wide)的配置文件为machine.config,存在于%SystemRoot%/Microsoft.net/Framework/V1.0.nnnn/CONFIG目录下。对于应用程序范围(application-wide)的配置文件,普通应用程序是应用程序目录下,文件名为EXE文件名后加config扩展名。ASP.NET为web.config。
28. 配置文件为XML语言文件,总有一个configuration的根元素。这些配置文件的设置控制了探测路径以及发行者版本策略模式。此外,dependentAssembly元素被用于对每个依赖的程序集制定版本和定位设置。(配置文件在中文版P36页有范例)。
29. 版本策略在三个级别上指定:应用程序(per application)à 组件(per component)à 机器(per machine)。前者输出为后者的输入。
30. 除了特定应用程序和计算机范围的配置文件外,给定的程序集还有发行者策略(publisher policy)。它由开发人员声明,标明哪些版本是互相兼容的。
31. 中文版P39页——展示了程序集解析器寻找适合的程序集文件的整个过程。
32. 为了避免二义性,程序集解析器只有在被请求的程序集名字中包含公钥时才查找GAC。公钥既能够作为程序集引用或者Assembly.Load参数的一部分显式地被提供,也可以通过qualityAssembly配置文件隐式地被提供。
33. GAC由系统级的组件(FUSION.DLL)控制,将DLL缓存存储在%WINNT%/Assembly目录下。
34. CODEBASE提示配置文件实例:中文版P41页
35. 如果程序集解析器通过GAC或CODEBASE提示都无法定位程序集,那么程序集解析器将对于应用程序根目录相关的目录进行查找。这个查找被称为探测(probing)。(中文书P43 - P45页)
36. 程序集被版本化为一个单元。如果替换程序集中文件的一个子集,而不更新版本号,将导致不可预测的结果。如果类型的功用约定改变了,类型的程序集必须赋予一个新的版本号。
37. CODEBASE提示,私有探测路径以及GAC就可以支持多个版本的并行安装,这允许给定的程序集的多个版本在文件系统中和平共处。然而,如果有多个这样的程序集被独立程序或者单个程序实际加载到内存中,那么,事情在某种程度上就是不可预测的。并行执行要比并行安装要难处理得多。
38. 共享类型需要被部署到单独的程序集中,它本身不会被版本化。(和《Applied》中描述接口应用程序的说法比较类似)。
39. 用于程序集的原数据具有三个特别的特性,他们允许开发人员制定程序集的版本是否同时能被加载。这些元数据为都被现行的程序集解析器和加载器所忽略。然而,他们确实能够起到提示作用,这个提示有望在CLR的未来版本中实施。