2Net本质论中文版Word下载.docx

上传人:b****1 文档编号:5342208 上传时间:2023-05-05 格式:DOCX 页数:35 大小:436.27KB
下载 相关 举报
2Net本质论中文版Word下载.docx_第1页
第1页 / 共35页
2Net本质论中文版Word下载.docx_第2页
第2页 / 共35页
2Net本质论中文版Word下载.docx_第3页
第3页 / 共35页
2Net本质论中文版Word下载.docx_第4页
第4页 / 共35页
2Net本质论中文版Word下载.docx_第5页
第5页 / 共35页
2Net本质论中文版Word下载.docx_第6页
第6页 / 共35页
2Net本质论中文版Word下载.docx_第7页
第7页 / 共35页
2Net本质论中文版Word下载.docx_第8页
第8页 / 共35页
2Net本质论中文版Word下载.docx_第9页
第9页 / 共35页
2Net本质论中文版Word下载.docx_第10页
第10页 / 共35页
2Net本质论中文版Word下载.docx_第11页
第11页 / 共35页
2Net本质论中文版Word下载.docx_第12页
第12页 / 共35页
2Net本质论中文版Word下载.docx_第13页
第13页 / 共35页
2Net本质论中文版Word下载.docx_第14页
第14页 / 共35页
2Net本质论中文版Word下载.docx_第15页
第15页 / 共35页
2Net本质论中文版Word下载.docx_第16页
第16页 / 共35页
2Net本质论中文版Word下载.docx_第17页
第17页 / 共35页
2Net本质论中文版Word下载.docx_第18页
第18页 / 共35页
2Net本质论中文版Word下载.docx_第19页
第19页 / 共35页
2Net本质论中文版Word下载.docx_第20页
第20页 / 共35页
亲,该文档总共35页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

2Net本质论中文版Word下载.docx

《2Net本质论中文版Word下载.docx》由会员分享,可在线阅读,更多相关《2Net本质论中文版Word下载.docx(35页珍藏版)》请在冰点文库上搜索。

2Net本质论中文版Word下载.docx

然而,对绝大多数开发人员来说,他们只是需要在开发时生成代码,而不是运行时,对此CLR编译器完全能够胜任。

C#编译器(CSC.EXE)、VB.NET编译器(VBC.EXE)和C++编译器(CL.EXE)都能够将源代码翻译成CLR模块。

各个编译器通过命令行开关控制产生的

表2.1 模块输出选项

C#/VB.NET

C++

直接可加载的?

从Shell中可直接运行?

可访问控制台?

/t:

exe

/CLR

总是

winexe

/CLR/link

/subsystem:

windows

从不

library

/CLR/LD

依赖主机(Host-dependent)

module

/CLR:

NOASSEMBLY

/LD

模块种类。

如表2.1所示,有4个可能的选项。

在C#和VB.NET中,通过/target命令行开关(或者其快捷形式/t)选择目标文件的种类。

C++编译器可以使用多个开关的组合;

不过,通过/CLR开关,强制C++编译器生成CLR兼容的模块。

下面所用到的C#和VB.NET开关,将采用它们的快捷形式。

选项/t:

module产生“未加工的(raw)”模块,其文件扩展名默认为.netmodule。

这种格式的模块不能独立地部署,CLR也不能直接加载它们。

准确地说,开发人员必须在部署前,将这些“未加工的”模块与成型的组件(被称为程序集)进行关联。

相比之下,用/t:

library选项编译产生的模块,能够包含附加的元数据,允许开发人员将其作为独立代码进行部署。

library编译产生的模块,其文件扩展名默认为.DLL。

用/t:

library编译产生的模块能被CLR直接加载,但不能从命令外壳或Windows资源管理器中作为可执行程序启动。

如果要产生可执行程序,你必须采用/t:

exe或者/t:

winexe选项。

这两个选项均产生扩展名为.EXE的文件,唯一的差别是:

前者假定为控制台UI子系统使用,后者则假定为GUI子系统。

如果没有指定/t选项,默认为/t:

exe。

不管是使用/t:

exe还是/t:

winexe选项产生的模块,都必须定义一个初始入口点(initialentrypoint)。

初始入口点是程序启动时CLR将自动执行的方法。

程序员必须将这个方法声明为static,并且,在C#或VB.NET中,还必须命名为Main。

程序员能够将入口点方法声明为无返回值,或者返回int型值。

他们也可以将其声明为无参数形式,或者接受一个字符串数组的参数,它包含从外壳程序输入的命令行参数。

下面是C#中Main方法的四种合法的实现。

staticvoidMain(){}

staticvoidMain(string[]argv){}

staticvoidMain(){return0;

}

staticvoidMain(string[]argv){return0;

对应的VB.NET代码为:

sharedsubMain():

endsub

sharedsubMain(argvasstring()):

sharedfunctionMain():

return0:

endfunction

sharedfunctionMain(argvasstring())

return0

endfunction

注意,这些方法并不是必须声明为public。

不过,程序员只能在类型定义中声明Main方法,尽管类型名称并不重要。

下面是最小的C#程序,只是向控制台打印字符串“Hello,world”。

classmyapp{

staticvoidMain(){

System.Console.WriteLine("

Hello,World"

);

}

在这个例子中,只有一个类,其中包含一个名为Main的静态方法。

如果源文件包含多个类型,都有名为Main的静态方法,那么,C#或VB.NET编

译可能无所适从(甚至导致错误)。

为了解决这种二义性,程序员可以采用/main命令行开关,告诉C#或VB.NET编译器哪个类型将用作程序的初始入口点。

程序集定义

为了部署CLR模块,开发人员首先必须将其归属于一个程序集(assembly)。

程序集就是一个或多个模块的逻辑集合。

如前面讨论过的那样,模块是以字节流形式存在的物理构件,通常存放在文件系统中。

程序集是逻辑构件,并且通过独立于位置的名字进行引用。

而这个名字必须翻译为文件系统中或Internet上的物理路径。

那些物理路径最终指向一个或多个包含类型定义、代码以及资源的模块。

尽管程序集可能由多个模块组成,但是一个模块往往只属于一个程序集。

假如出现两个程序集都引用一个公共模块的情况,将作如何处理?

这时,CLR将这个公共模块视为两个不同的模块,即公共模块中的每个类型都有两个不同的拷贝。

基于上述理由,本章剩余部分将假定一个模块只明确地属于一个程序集。

CLR允许开发人员由多个模块组建程序集,主要是为了支持将那些不经常访问的代码的加载区分开来,同时不用为它们形成单独的封装边界。

这个特征在开发人员采用代码下载时特别有用,因为他们可以先只下载初始模块,根据需求才会下载下一个模块。

多模块程序集还可以是混合语言的。

这样,开发人员既可以采用高生产率的语言(例如,Logo.NET),用于完成大部分工作,同时,采用更为灵活的语言(例如,C++)编写底层代码。

通过将这两个模块结合为单个程序集,开发人员能够同时将C++和Logo.NET代码作为一个原子单元进行引用、部署以及版本控制。

在CLR中,程序集是部署的“原子”,被用来对CLR模块进行打包、加载、分布以及版本控制。

虽然程序集可能包括多个模块以及辅助文件,但程序集本身被作为原子单元进行命名和版本化。

如果程序集的某个模块版本发生变化,那么,整个程序集必须重新部署,因为版本号是程序集名字的一部分,而不是底层模块名字的一部分。

模块一般都依赖于来自其他程序集的类型。

最起码每个模块都依赖于定义在mscorlib程序集中的类型,例如,System.Object和System.String等等。

每个CLR模块都包含一个程序集名字的列表,指明该模块所使用的程序集。

对于这些程序集以外的引用,它们只是使用了程序集的逻辑名字,而不包含底层模块名或者位置信息。

CLR将负责在运行时将这些程序集的逻辑名字转换为模块的路径名。

本章后面还将专门讨论。

为了促使CLR能够找到程序集中不同部分,每个程序集都正好有一个模块,其元数据包含了程序集清单(assemblymanifest)。

程序集清单是CLR元数据中附加的一部分,相当于附加的类型定义和代码的附属文件目录。

CLR能够直接加载包含程序集清单的模块。

对于没有程序集清单的模块,CLR只能先加载含有程序集清单的模块,并且,该清单引用了这些没有清单的模块,从而间接地加载它们。

图2.2展示了两个模块:

一个含有程序集清单,一个则没有。

注意4个/t编译选项,只有/t:

module产生没有程序集清单的模块。

图2.3展示了一个使用多模块程序集的应用程序,示例2.1则是产生它的MAKEFILE文件内容。

在这个例子中,module就是不含程序集清单的模块。

为了让这个模块有用,就需要第二个模块(本例为component.dll)提供一个程序集清单,并将module作为下级模块进行引用。

当编译所包含的程序集时,要使用/addmodule开关。

在这个程序集生成之后,所有在component.dll和module中定义的

图2.2:

模块和程序集

图2.3:

使用CSC.EXE编译多模块程序集

类型都通过程序集的名字(component)确定作用域。

应用程序(例如,application.exe)使用/r编译选项,来引用含有程序集清单的模块。

这样,使得两个模块中的类型都能为程序所用。

示例2.1:

使用CSC.EXE和NMAKE编译多模块程序集

#modulecannotbeloadedasisuntilanassembly

#iscreated

module:

code.cs

csc/t:

modulecode.cs

#typesincomponent.cscanseeinternalandpublicmembers

#andtypesdefinedincode.cs

component.dll:

component.csmodule

library/addmodule:

modulecomponent.cs

#typesinapplication.cscannotseeinternalmembersand

#typesdefinedincode.cs(orcomponent.cs)

application.exe:

application.cscomponent.dll

exe/r:

component.dllapplication.cs

程序集清单存放在一个明确的模块中,并且包含了用于定位类型和资源的所有信息,而这些类型和资源则被定义为程序集的一部分。

图2.4展示了被组合成单个程序集的一组模块,在构建它们时需要相应的CSC.EXE开关。

注意在这个例子中,程序集清单包含对下级模块module和module的文件引用列表。

除了这些文件引用之外,这些下级模块的每个公共类型都通过.classextern指令列出来。

这样,就有了公共类型的完整列表,而不用对程序集中每个模块都遍历元数据。

列表的各项指明了类型所在的文件名,以及唯一标识模块中类型的数值的元数据标记(numericmetadatatoken)。

图2.4:

多模块程序集

最后,含有程序集清单的模块将包含外部引用程序集的主要列表。

列表由程序集中每个模块的依赖关系(dependency)组成,而不仅仅是当前模块的依赖关系。

这样,通过加载单个文件,就能找到程序集所有的依赖关系。

程序集形成一个封装边界(encapsulationboundary),在程序集之间的访问中保护内部实现细节。

程序员可以对类型的成员(例如,字段、方法、构造函数等)实施保护,也可以保护整个类型。

将类型成员标注为internal,将导致它只对同一程序集的模块是可用的。

假如将类型成员标注为public,则导致它对所有代码(当前程序集内部以及外部)是可用的。

假如类型中单独成员(例如,方法、字段、构造函数)还能标注为private,只有该声明类型中的方法和构造函数才能访问。

这样对于组件内部的封装,编程上与传统的C++风格一致。

类似的情形,程序员能将类型成员标注为protected,

它放宽了private所允许的访问限制,使得派生类型的方法和构造函数也能访问该成员。

访问修饰符protected和internal可以组合在一起使用,这样既能够访问当前类型派生的类型,也能够访问同一程序集中的类型。

表2.2展示了特定语言修饰符运用到类型以及单独成员中的情形。

注意在C#中,标注为protectedinternal的成员要么只对同一程序集中的访问方法开放,要么只对派生类型的访问方法开放。

CLR还支持一种访问修饰符(在元数据中的标注为famandassem),既对同一程序集中的访问方法公开,又对派生类型的访问方法公开。

不过,VB.NET和C#并不允许程序员指定这种访问修饰符。

表2.2 访问修饰符

C#

VB.NET

意义

类型

public

Public

访问类型不受限制

internal

Friend

类型只在程序集内部可访问

成员

Public*

访问成员不受限制

成员只在程序集内部可访问

protected

Protected

访问仅限于包含类或者从包含类派生的子类型

protectedinternal

ProtectedFriend

访问仅限于包含类以及从包含类派生的子类型,或者当前程序集的其他类型

Private

Private*

访问仅限于包含类型

*在VB.NET中,通过关键字Dim声明的方法默认为Public,而字段默认为Private。

程序集中定义类型Customer,而在运行时却不发生混淆,但是,这并不能帮助程序员在单个程序中使用两个或多个同名的类型定义。

因为符号化的类型名总是Customer,而不管哪个程序集定义它。

为了解决这种大多数编程语言的限制,CLR类型名会有一个命名空间前缀(namespaceprefix)。

这个前缀是一个字符串,一般以开发人员的组织名(例如,Microsoft、AcmeCorp)开始;

如果是.NETFramework的一部分话,则以System开始。

程序集的命名约定通常是基于命名空间前缀。

例如,.NETXML堆栈被部署在System.Xml程序集中,它包含的所有类型都使用System.Xml的命名空间前缀。

这仅仅是一个约定,而不是规则。

例如,类型System.Object存放在名为mscorlib程序集中,而不是名为System的程序集中,尽管也确实存在名为System的程序集。

程序集名字

每个程序集采用四部(four-part)名字,作为唯一的标识。

这四部名字由名称、文化、开发人员以及组件版本构成。

这些名字被存放于程序集自身的程序集清单(assemblymanifest)中,以及引用它的所有程序集的程序集清单中。

在加载时,CLR使用四部程序集名字,找到正确的组件。

CLR提供System.Reflection.AssemblyName类型,便于开发人员对程序集名字进行可编程地访问,具体则是调用该类型的System.Reflection.Assembly.GetName方法。

程序集名字的Name属性往往与程序集清单的底层文件名(不包含任何文件扩展名,尽管它们可能有用)相对应。

这是程序集名字中唯一的不可任选的部分。

对于简单的情形,CLR在加载时只需要Name属性就能够定位正确的组件。

当构建(build)程序集时,名字的这个部分是由编译器根据目标文件名自动选择的。

所有的程序集名字都有一个四部分版本号,其形式为Major.Minor.Build.Revision。

如果你没有显式地设置这个版本号,

表2.3AssemblyVersion特性

特性参数

实际值

1

1.0.0.0

1.2

1.2.0.0

1.2.3

1.2.3.0

1.2.3.4

1.2.*

1.2.d.s

1.2.3.*

1.2.3.s

无参数

0.0.0.0

*这里,d是指从2000年2月1日以来的天数,s是从子夜以来的秒数除以2所得的值

默认值将是0.0.0.0。

版本号是在程序构建时设置的,比较典型的方式就是在源代码中使用定制特性。

System.Reflection.AssemblyVersion特性能够接受各种的字符串格式,如表2.3所示。

当你指定版本号时,Major版本号是必须的。

任何缺省部分被假定为零。

在构建时(buildtime),如果Revision部分被指定为*(星号),那么,编译器将利用时钟的时间,为每次编译生成一个单调递增的修订版本号。

如果Build号被指定为*,那么,发射(emit)到程序集清单的Build号,是基于2000年2月1日起的天数,确保每一天程序集都有自己的唯一的构建号。

不过,给定的构建号将只能适用于给定的24小时制。

你不能将版本号的Major或Minor部分指定为*。

稍后,本章将讨论程序集加载器和解析器如何使用程序集的版本。

程序集名字能够包含CultureInfo特性,它能够标识组件开发所用到的语言和国家代码,也就是组件应用的语言环境。

开发人员通过System.Reflection.AssemblyCulture特性指定CultureInfo。

这是Internet工程任务组[InternetEngineeringTaskForce(IETF)]发布的1766号请求注释[RequestforComments(RFC)]所规定的两部分字符串,即字符串的第一部分使用两个小写字母标识语言,第二(可选择)部分使用两个大写字符标识地理区域。

例如,字符串”en-US”标识为美国英语。

含有CultureInfo特性的程序集不能包括代码;

准确地说,它们必须是纯资源(resource-only)

的程序集[也称为辅助(satellite)程序集],只能包含区域化的字符串(localizedstring)和用户界面元素。

对于包含代码的单个DLL,辅助程序集允许它们根据被部署的区域有选择地加载(和下载)相应的区域化资源。

包含代码的程序集(也可以说是绝大多数程序集)被认为是文化无关的(culture-neutral),因而也就没有文化标识符。

最后,程序集名字包含一个公钥(publickey),它可以标识组件的开发人员。

一个程序集引用既可以使用完全的128字节的公钥,也可以使用8字节的公钥标记。

公钥(或者公钥标记)被用作处理组织间的文件名冲突。

例如,在内存中和磁盘上可能存在多个utilities.dll组件,它们来自不同的组织,每个组件都被确保拥有唯一的公钥。

下一节我们将更详细地讨论公钥管理。

由于有时必须手工引用程序集(例如,在配置文件中使用),因此,CLR定义了一个标准格式,用于将程序集的四部名字编写为字符串。

这个格式被称为程序集的显示名字(displayname)。

程序集的显示名字总是以程序集的简单Name开始,接着是以逗号为分隔符的属性列表,分别与程序集名字的其它三个属性相对应,并且是可选的。

如果四部名字完全被指定,对应的程序集引用被称为完全限定引用(fullyqualifiedreference)。

如果缺省一个或者更多的属性,则对应的程序集引用被称为部分限定引用(partiallyqualifiedreference)。

图2.5展示了一个显示名字,以及用来控制每个属性的对应的CLR特性。

注意,如果期望程序集没有文化限制,那么,显示名字必须使用Culture=neutral给予标明。

同样,如果期望程序集不带公钥,显示名字也必须通过PublicKeyToken=null标明。

这两种情形与不带Culture或PublicKeyToken属性的显示名字绝然不同。

简单省略显示名字的某些属性,将导致生成一个部分限定名字,它允许匹配任何Culture或PublicKeyToken。

图2.5:

完全限定的程序集名

一般来说,应该避免使用部分限定程序集名字;

否则,CLR的许多部分将以非预期的(甚至令人不满意的)方式工作。

然而,为了处理忽略该警告的代码,CLR允许在配置文件中,将部分程序集名字进行完全限定。

例如,考虑下面的应用程序配置文件:

<

configuration>

<

runtime>

asm:

assemblyBinding

xmlns:

asm="

urn:

schemas-microsoft-com:

asm.v1"

>

qualifyAssemblypartialName="

AcmeCorp.Code"

fullName="

AcmeCorp.Code,version=1.0.0.0,

publicKeyToken=a1690a5ea44bab32,culture=neutral"

/>

/asm:

assemblyBinding>

/runtime>

这个配置允许下列对Assembly.Load的调用:

Assemblyassm=Assembly.Load("

前面的调用与下面的调用一样:

AcmeCorp.Code,"

+

"

version=1.0.0.0,publicKeyToken=a1690a5ea44bab32,"

culture=neutral"

PartialName特性必须与Assembly.Load的参数完全匹配;

也就是说,每个在对Assembly.Load调用中指定的属性,也必须存在于配置文件的PartialName特性中。

并且,在PartialName特性中指定的每个属性,也必须在对Assembly.Load的调用中出现。

稍后,本章将讨论如何定位配置文件。

公钥和程序集

CLR利用公钥技术对组件的开发人员进行唯一标识,同时也保护组件,使它在离开原创者之后不被篡改。

每个程序集有能标识开发人员的公钥,它嵌入在程序集中。

带有公钥的程序集还含有数字签名(digitalsignature),它是在程序集首次发布之前生成的;

数字签名还提供了程序集清单的加密哈希值(hash),而程序集清单本身包含了所有附属模块的哈希值。

这样就保证了程序集一旦被发布,程序集中的代码和资源将不再被改变。

数据签名能够只使用公钥进行检验;

而签名只能带有对应的私钥(privatekey)才能生成。

由此,组织必须更为谨慎在保护私钥。

现行的CLR版本利用RS

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2