您的位置:首页 > 编程语言 > C#

《CLR via C# 》读书笔记(1) -- .Net程序是如何生成的

2012-11-20 13:24 411 查看
说到.NET基础,我觉得应该首先应该要知道一组概念,我觉得作为.NET程序员,这应该算是常识。有可能我目前的理解也不算正确,希望能在以后的积累中逐步完善。

CLR

- CLR (Common Language Runtime)它为.NET Application提供一个运行时的环境。毕竟.NET程序和普通的Windows应用程序(比如说用C++开发的程序)运行方式是不一样的。在

运行时,它有自己的内存管理机制,有自己的执行模型,有自己的异常处理,有自己的线程同步等。而这些都是由CLR提供。相当于一个容器。

CTS

- CTS (Common Type System) .Net是一个基于类型的平台,所有的事物都必须被一个类型所包含。没有像C++中的全局变量,全局函数这类东西。那么CTS是一系列用来规范

类型的规则。比如说:规定类型可以包含字段,方法,属性,事件,规定类型可以继承,规定类型的可访问类型可以有private, public, internal等。个人理解是一种语法规则。

CLS

- CLS (Common Language Specification) CLR其实提供了很多的功能,而每一种面向CLR的语言(比如说C#,VB.NET)可能不需要暴露CLR所有的功能给开发人员。但是如果每种语言所支持的

CLR功能不一样,相互之间的调用便会出现问题了(目前可以举出一个例子:CLR是支持throw 任何类型,VB.NET是完全支持CLR的,但是C#只支持throw Exception的派生类。如果在C#中调用VB.NET的

代码,那VB.NET中的有些throw肯定无法在C#中catch住。)。为了能够跨语言调用,必须有一个规范来统一各个语言所必须支持CLR中的功能集。这个规范便是CLS。他定义了CLR强大功能中的一个子集合,这是

所有面向CLR的语言必须要支持的。这样能才能实现跨语言的调用。

程序集

- 程序集(Assembly)我觉得用最通俗的语言讲就是一些类的集合。但是这样说应该是比较片面的,至少程序集里面还能嵌入资源文件。

官方说法应该是程序集是由一个或多个模块加上资源文件组成,每个模块由描述该模块所包含/引用类型的元数据和IL代码组成。

回到和标题相关的内容,平常我们编写一个.NET程序的过程应该是

1. 创建一个VS Project

2. 编写代码

3. 编译Project,接着VS便给我们产生了一个exe程序

4. 我们双击一下这个exe程序,我们绘制的界面就出现了。

作为.NET程序员,我觉得应该要了解得更多一点。这样才能知其所以然,呵呵。

剖析生成的exe/dll文件
1. 文件组成结构
编绎器生成的exe/dll的组成结构为:PE32(+) Header,CLR Header,程序集的元数据以及源代码经过编绎后生成的IL代码。具体表示内容见下表:

View Code // Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly Entity
{
.custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 06 45 6E 74 69 74 79 00 00 ) // ...Entity..
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 30 01 00 54 // ,Version=v4.0..T
0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C // ..FrameworkDispl
61 79 4E 61 6D 65 10 2E 4E 45 54 20 46 72 61 6D // ayName..NET Fram
65 77 6F 72 6B 20 34 ) // ework 4
.custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 06 45 6E 74 69 74 79 00 00 ) // ...Entity..
.custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20 // ...Copyright ..
20 32 30 31 32 00 00 ) // 2012..
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 31 38 37 31 33 65 65 31 2D 63 61 62 62 // ..$18713ee1-cabb
2D 34 39 31 61 2D 39 34 35 63 2D 36 31 63 30 63 // -491a-945c-61c0c
32 62 36 61 39 36 64 00 00 ) // 2b6a96d..
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0..

// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )

.publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00 // .$..............
00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00 // .$..RSA1........
A1 C0 32 95 08 03 92 3F 1B 1D BA 20 B0 B4 1B F5 // ..2....?... ....
9C 3A E5 C5 88 50 74 7B 66 4D A9 A6 4C CB D5 30 // .:...Pt{fM..L..0
80 5B FB 98 B3 4B 55 CE D6 BC 53 BF 80 A7 18 39 // .[...KU...S....9
DF 9E 3C AD 5F 34 B8 B0 6F AF 87 CD 9B 36 66 F3 // ..<._4..o....6f.
27 FF 7E E9 4E 52 5D 17 61 49 F6 89 54 2D B0 AF // '.~.NR].aI..T-..
FD 7E EA 75 D5 A7 47 08 10 FD 18 91 99 4E 99 DA // .~.u..G......N..
78 0A DE BE 1F D7 00 21 A5 A5 99 0B 89 53 43 8E // x......!.....SC.
AB 78 5D F9 A1 C6 16 23 4E C6 65 3D F5 8F D8 DC ) // .x]....#N.e=....
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module Entity.dll
// MVID: {72590280-AC77-4C2F-BA62-BF18ABD776B2}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000009 // ILONLY
// Image base: 0x03760000
可以看到清单元数据中包含了一个PublicKey元素(即公钥)。
2. 使用

当加载一个强名的程序集时,必须提供强名标识符

AssemblyName assemblyName = new AssemblyName("Entity, Version=1.0.0.0, culture=neutral, PublicKeyToken=65fed09757d375fd");
Assembly entityAssembly = Assembly.Load(assemblyName); 此处的PublicKeyToken是公钥的64位Hash值。可以使用SN工具来获取私钥/公钥对文件中的公钥以及公钥标记。

此处如果版本不对:

AssemblyName assemblyName = new AssemblyName("Entity, Version=1.0.0.1, culture=neutral, PublicKeyToken=65fed09757d375fd");
Assembly entityAssembly = Assembly.Load(assemblyName);或公钥标记不对:

AssemblyName assemblyName = new AssemblyName("Entity, Version=1.0.0.0, culture=neutral, PublicKeyToken=65fed09757d375fda");
Assembly entityAssembly = Assembly.Load(assemblyName);都会导致该程序集加载失败:


终于写完了这一节,感觉写点东西比看东西费劲很多啊。不过在写的过程中还是加深了自己的理解。勉励一下自己,继续坚持。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐