译:《Professional C# 4.0 and .NET 4》 第一章 .Net体系架构(2)

以下内容原文见《Professional C# 4.0 and .NET 4》 -> Part1: The C# Language -> Chapter 1: .NET Architecture
原文作者:Christian Nagel, Bill Evjen, Jay Glynn, Karli Watson, Morgan Skinner
翻译:Sam.Sha – ycoder.com
备注:只翻译UI技术相关的,不包含ASP

程序集

一个程序集是个逻辑单位,包含了针对.NET Framework编译的代码,本节不会详细介绍,在第18章“Assemblies”会作全面的说明,这里只作主要点概要

程序集完全是自描述的,他是一个逻辑单位而不是物理单位,也就是说他可能被存放在多个文件中(实际上,动态程序集存放在内存中而不是文件),如果一个程序集存放在多个文件中,其中有一个主文件包含了入口和其他程序集文件的位置

注意可运行代码和库代码都使用了相同的程序集结构,他们唯一的区别是,可执行程序集包含了一个主程序入口,而库程序集没有。

程序集的一个重要特征是,它既包含了对应代码的类型方法元数据描述,也包含了程序集自己的元数据描述,程序集元数据包含在被称为程序清单的位置,允许检查程序集版本和完整性。

ildasm, 一个基于windows的实用程序,可以用来检查程序集的内容,包括程序清单和元数据,ildasm会在18章节做介绍

实际上,程序集包含了程序的元数据意味着任何程序或着程序集可以调用给定程序集中的代码,而不需要引用注册表或者其他任何数据源,就能找出如何使用这个程序集,这是对以前COM方式重大突破,原来的方式需要从注册表获取组件和接口的GUIDs是什么,而具体的方法和属性需要从类型库中读取。

将数据分放在三处地方意味着增加了同步的风险,也妨碍了其他软件成功调用这个组件,使用程序集则可以避免这些问题,因为所有的元数据与程序可执行指令存放在一起,即使是包含多个文件的程序集也不用担心同步的问题,因为包含程序集入口的文件中存放了其他文件内容的详细信息和hash信息,所以如果其他某个文件被替换或者任何方式的修改,都会被察觉,程序集会拒绝加载。

程序集有两种方式:私有和共享

私有程序集:

私有程序集是最简单的类型,他们常常只被装在他的那个软件所使用,通常你装载一个私有程序集的情形是,你提供一个应用程序,包含一个可执行文件和一些库文件,这些库中的代码只能被这个应用程序所使用

系统会保证私有程序集不被其他程序使用,因为一个程序只能加载位于主程序相同目录或者子目录下的私有程序集。

因为通常软件安装在自己的目录,这样就避免了其他程序或包覆盖、修改或无意间调用私有程序集的风险,因为私有程序集只能被他所在的程序访问,这样给了我们更多控制那些软件使用他们的控制能力,因此不需要为安全担心,因为没有风险,如过假设有其他的软件覆盖了你的某个程序集,并使用相同的新版本(除了软件,也可能是专门设计恶意破坏的),这时命名冲突也不会有问题,如果两个私有程序集中包含相同名称的类,这也不要紧,因为任何给定的程序只能看到一组私有程序集。

因为私有程序集是自包含的,所以它的部署也很简单,你只需要把相应的文件放到相应的目录就可以了(无需添加注册表项),这个过程被称为零影响(xcopy)安装

共享程序集

共享程序集的目的是共享库,让任何程序都可以访问,因为任何软件都可以访问共享这个共享程序集,所以更多的风险需要预防:

1、命名冲突,如果另外一个公司的共享程序集实现类型与你的共享程序集使用相同的名称,这可能导致严重问题,因为理论上客户端代码是可以同时访问两个程序集

2、同一个程序集被不同版本覆盖的风险,因为新版本不一定符合原有客户端程序

这些问题的解决办法是将共享程序集放置在特殊的文件目录树下,称作全局程序集缓存(GAC),不像私有程序集,不能简单的拷贝程序集到指定目录,而需要特殊的安装到缓存。这一过程可以借助.NET实用工具,他会检查这个程序集,并将其安装到该程序集缓存的子目录,保证程序集的完整性

为了解决命名冲突的问题,共享程序集提供了一个通过私钥加密的名称(私有程序集的名称就是他主文件的名称),这个名称称为强名,这个名称保证是唯一的,且必须被使用这个共享程序集的程序所引用。

程序集覆盖的风险,可以通过在程序集中指定特殊的版本信息来避免,运行并行安装

因为程序集存放有元数据,包含类型和成员的详细信息,所以可以通过程序获取这些元数据,详细介绍在14章节,这种技术被称为反射,这增加了有趣的可能性,因为这意味着委托代码实际上可以检查另一委托代码,甚至分析他自己,得出代码相关的信息,最常使用的是获取属性细节,同样你可以通过反射实现其他目的,如同过给定的类名和方法名称实例化一个类,和访问方法,通过这种方式,你可以在程序运行时,根据用户输入(动态绑定),选择类调用什么方法,而不是在编译时决定。

并行编程

.NET Framework 4引入了能够采用双核或四核处理器的能力,这种并行运算的能力意味着可以将工作分割成几块在多个处理器上运行,新的并行程序API让编写多线程代码变得更安全,但必须注意的是,这需要涉及到更多同步的东西,比如锁

新的并行编程能力提供了新的任务并行库,称为:PLING执行引擎,并行程序将在20章节中的”线程,任务和同步”作介绍

.NET Framework类

或许编写托管代码的一个好处,至少从程序员的角度看是,可以使用.NET基础库,.NET基础类大量托管代码类集合,允许你通过Windows API实现任何的任务,这些类使用与IL相同的对象模型,基于单一继承,这意味着你既可以继承这些类,也可以直接在自己的类中调用。

.NET基础类库的伟大在于他们的设计直观好用,举个例子,启动一个线程,调用Thread类的Start方法即可,无效一个文本框,你只需要设置TextBox对象的Enabled属性为false,这种方式对于Java和VB开发者来说是很熟悉的,它们的类库也是像这样容易使用,这也解救了C++开发者,它们长年累月需要使用类似GetDIBits(), RegisterWndClassEx()和IsEquallID()这样的函数,以及整个中过多需要传递Windows函数句柄的函数,当然,C++开发者更方便访问所有的Windows API,不像Java和VB开发者使用各自语言访问基础操作系统函数时会有种种条件的限制。而.Net 基础类的新亮点就是整合了这些基础类库,让大部分的Windows API可以方便的访问,还有一些Windows特性不能在基础类中调用,这时你需要通过API函数去访问,但一般来说,这些都是些奇特的需求,对于日常使用,你会发现.NET基础库足够了,此外,如果你需要调用API函数,.NET提供了一种所谓的平台调用,可以确保数据类型的正确转换,这比起直接使用C++代码要容易——使用C#,Visual Basic 2010 或者C++都可以。

WinCV是一个Windows实用工具,可以用于浏览基础类库中的类,结构,接口以及枚举,WinCV将在16章节的“Visual Studio 2010.”中介绍,在我们完成C#语法介绍之后,第三章将介绍.NET的基础类,虽然名义上是说.NET基本类,实际上本书主要讲的是.NET4的基本类库,这是因为基础类太庞大了,作为一个初略的概要,.NET 3.5覆盖的基础类就包含下面的内容:

➤ IL核心功能(包含在第三章将讨论的CTS中的原始类型)

➤ Windows GUI支持和控件(见39章“Windows Forms”和35章”Core WPF”)

➤ Web Forms(40章的ASP.NET,”Core ASP.NET”以及41章的”ASP.NET Features”)

➤ 数据访问(ADO.NET; see Chapters 30, “Core ADO.NET” 34, “.NET Programming with SQL Server,” and 33, “Manipulating XML”)

➤ Directory access (see Chapter 52 on the Web, “Directory Services”)

➤ File system and registry access (see Chapter 29, “Manipulating Files and the Registry”)

➤ Networking and web browsing (see Chapter 24, “Networking”)

➤ .NET attributes and reflection (see Chapter 14)

➤ Access to aspects of the Windows OS (environment variables and so on; see Chapter 21)

➤ COM interoperability (see Chapter 51 on the Web, “Enterprise Services” and Chapter 26)

顺便说一点,根据微软的源代码,实际上.NET基础类库中有很大一部分是用C#编写的

名称空间

为避免命名冲突的一种方式,和java类似,这部分不翻译了

A namespace is no more than a grouping of data types, but it has the effect that the names of all data types within a namespace are automatically prefixed with the name of the namespace. It is also possible to nest namespaces within each other. For example, most of the general-purpose .NET base classes are in a namespace called System. The base class Array is in this namespace, so its full name is System.Array.

.NET requires all types to be defined in a namespace; for example, you could place your Customer class in a namespace called YourCompanyName. This class would have the full name YourCompanyName.Customer.

If a namespace is not explicitly supplied, the type will be added to a nameless global namespace.

Microsoft recommends that for most purposes you supply at least two nested namespace names: the first one represents the name of your company, and the second one represents the name of the technology or software package of which the class is a member, such as YourCompanyName.SalesServices.Customer. This protects, in most situations, the classes in your application from possible name clashes with classes written by other organizations.

Chapter 2 looks more closely at namespaces.


六 × 3 =