Effective C#之Chapter 4: Creating Binary Components

rel="File-List" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"> rel="themeData" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"> rel="colorSchemeMapping" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml">

Chapter 4. Creating Binary Components

创建二进制组件

Creating binary components has much in common with creating classes: You are trying to separate and partition functionality. The difference is that binary components enable you to deliver those discrete bits of functionality separately. You create component assemblies to simplify sharing logic, facilitate cross-language programming, and simplify deployment.

创建二进制组件与创建类有很多共同点:试图对功能进行分组、分离。不同处在于二进制组件允许你单独的发布那些离散的功能。创建组件程序集,可以简化共享的逻辑、方便跨语言交叉编程、简化部署。

Assemblies are component packages in .NET. Each assembly can be released and upgraded independently. How easily you can upgrade a deployed application on an assembly-by-assembly basis depends on how well you minimize the coupling between assemblies. Minimizing coupling means more than just minimizing the compilation dependencies between assemblies. It also means building assemblies that you can easily upgrade in the field with new versions. This chapter is about creating assemblies that are easy to use, easy to deploy, and easy to upgrade.

.Net里面,程序集是组件包。每个程序集可以独立的发布和更新。对已经部署好的基于程序集的应用程序,进行更新的难易程度取决于这些程序集之间的耦合度,耦合度越低,更新越容易。最小化耦合性不仅意味着最小化程序集之间的编译依赖性,同时也意味着需要构建可以在新版本里面很容易在这方面更新的程序集。本章讲述关于如何创建易使用、易部署、易更新的程序集。

The .NET environment is designed to support applications that consist of multiple binary components. Over time, you can upgrade those components independently, installing and upgrading one assembly in a multiassembly application. You must have some understanding of how the CLR finds and loads assemblies to utilize this feature. You also must create components that conform to certain expectations if you are to make the most of this binary upgrade. The rest of this introduction explains these concepts.

.Net环境被设计成支持多个二进制组件组成的应用程序。随着时间的流逝,你可以独立的更新那些组件,在多程序集应用程序里面安装和更新其中的一个程序集。为了利用一些特性,你应该对CLR如何查找和加载程序集有一定的理解。如果你要充分利用二进制更新方式,应该创建遵循一些特定期望的组件。本节介绍的剩下部分将解释这些概念。

The CLR loader does not load every referenced assembly when your program starts. Rather, the loader resolves assembly references when the runtime needs members in that assembly. This can be a method call or a data access request. The loader finds the referenced assembly, loads it, and JITs the necessary IL.

当程序启动时,CLR加载器并不加载每个引用到的程序集。当运行时需要程序集里面的成员时(可能是一个方法调用或者数据访问请求),加载器才对程序集引用进行解析。加载器查找并且加载引用的程序集,即时编译成必须的中间代码。

When the CLR needs to load an assembly, the first step is to determine what file gets loaded. The metadata for your assembly includes a record for each of the assemblies it references. This record is different for strong- and weak-named assemblies. A strong name consists of four items: the text name of the assembly, the version number, the culture attribute, and the public key token. If the requested assembly does not have a strong name, only the assembly name is part of the record. If you use strong names, your components will be less likely to be replaced by malicious components. Strong names also enable you to use config files to map the requested version to a new, improved version of a component.

CLR需要加载一个程序集的时候,第一步是决定加载哪个文件。程序集的元数据包含一个它引用的程序集的一个记录表。强命名和弱命名程序集的记录表是不同的。强命名由4部分组成:程序集的文本名字,版本号,语言文化特性,公共密钥标记。如果被请求的程序集不含有强命名,那么就只记录了程序集名称。如果你使用了强命名,你的组件将不大可能被恶意组件替换。强命名同时也允许你使用配置文件将被请求的版本映射到新的增强过的组件上面。

After determining the correct assembly and version, the CLR determines whether the assembly is already loaded into the current application context. If so, that assembly is used. If not, the CLR continues by looking for the assembly. If the requested assembly has a strong name, the CLR first searches the Global Assembly Cache (GAC). If the requested assembly is not in the GAC, the loader checks for a codebase directory in the configuration files. If a codebase directory exists, only that directory is searched for the requested assembly, If the requested assembly is not found in the codebase directory, the load fails.

在决定了正确的程序集和版本之后,CLR要判断该程序集是否已经被加载进了当前的应用程序上下文中。如果已经被加载了,就直接使用;如果没有被加载,继续查找该程序集。如果被请求的程序集是强命名的,那么,CLR将首先搜索全局程序集缓存(GAC)。如果被请求的程序集不在GAC里面,那么,加载器将检查在配置文件里面的代码路径。如果存在代码路径,那么将只搜索那个路径;如果在代码路径里面找不到被请求的程序集,加载就宣告失败了。

If there is no codebase directive, the loader searches a set of predefined directories:

如果没有基于代码的指示,加载器将搜索一些预定义的目录:

The application directory. This is the same location as the main application assembly.

应用程序目录。即,主应用程序程序集同样的目录。

The culture directory. This is a subdirectory under the application directory. The subdirectory name matches the current culture.

语言文化路径。这是在应用程序目录下面的一个子目录,它的名字和当前语言文化相匹配。

The assembly subdirectory. This subdirectory name matches the requested assembly name. These two can be combined in the form of [culture]/[assemblyname].

程序集子目录。该子目录的名称和被请求的程序集名称相匹配。这两项可以通过[culture]/[assemblyname]结合在一起。

The private binpath. This is a private directory defined in the application config file. This can also be combined with the culture and assembly path: [binpath]/[assemblyname], or [binpath]/[culture], or even [binpath]/[culture]/[assemblyname].

私有的运行路径。这是在应用程序的配置文件里面定义的私有路径。该项可以和语言文化以及程序集路径相组合:[binpath]/[assemblyname]或者 [binpath]/[culture]甚至 [binpath]/[culture]/[assemblyname]都可以。

You should remember three items from this discussion. First, only strong-named assemblies can be stored in the GAC. Second, you can use configuration files to modify the default behavior to upgrade individual strong-named assemblies in your application. Third, strong-named assemblies provide greater application security by preventing malicious tampering.

从这个讨论,你应该记住三点。首先,只有强命名程序集可以被存储在GAC中。第二,在应用程序里,你可以使用配置文件修改默认的行为,来更新个别单独的强命名程序集。第三,强命名程序集通过阻止恶意篡改来对应用程序提供更强大的安全保护。

This introduction into how the CLR loads assemblies should get you thinking about creating components that can be updated in the field. First, you should consider creating strong-named assemblies, with all the metadata records filled in. When you create projects in VS .NET, you should fill in all the attributes created in assemblyInfo.cs, including a complete version number. This makes it easier to upgrade the component in the field later. VS .NET creates three different sections in assemblyInfo.cs. The first is mostly informational:

CLR如何加载程序集的介绍,应该使你考虑创建可以通过在这方面进行更新的组件。首先,你应该考虑创建强命名的程序集,记录下所有的元数据。当你在VS.NET里面创建项目时,应该对所有在assemblyInfo.cs里面创建的特性进行填充,包括完整的版本号。这使得在以后要对组件在这方面进行更新更容易。VS.NETassemblyInfo.cs里面创建3个不同的部分。第一部分主要是信息性的:

[assembly: AssemblyTitle("My Assembly")]

[assembly: AssemblyDescription("This is the sample assembly")]

#if DEBUG

[assembly: AssemblyConfiguration("Debug")]

#else

[assembly: AssemblyConfiguration("Release")]

#endif

[assembly: AssemblyCompany("My company")]

[assembly: AssemblyProduct("It is part of a product")]

[assembly: AssemblyCopyright("Insert legal text here.")]

[assembly: AssemblyTrademark("More legal text")]

[assembly: AssemblyCulture("en-US")]

The last item, AssemblyCulture is filled in only for a localized assembly. If your assembly does not contain any localized resources, leave it blank. The string describing the culture conforms to the RFC 1766 standard.

最后一项,AssemblyCulture,只有当这是本地化的程序集时才被填充。如果你的程序集不包含任何本地资源,将该项留为空。该字符串描述了符合RFC 1766 标准的语言文化。

The next section contains the version number. VS .NET writes this:

下一部分,包含了版本号。VS.NET这样写:

[assembly: AssemblyVersion("1.0.*")]

AssemblyVersion contains four portions: Major.Minor.Build.Revision. The asterisk tells the compiler to fill in the build and revision using the current date and time. The build number contains the number of days since January 1, 2000. The revision contains the number of seconds since midnight local time, divided by 2. This algorithm guarantees that the build and revision numbers continue to grow: Each new build has a greater number than before.

程序集版本,包含4部分:主版本号.副版本号.编译版本号.修正版本号。星号告诉编译器使用当前日期和时间来填充编译版本号和修正版本号。编译版本号数字包含了从2000.2.1至今的天数。修正版本号数字包含了从本地午夜之今的秒数除以2。该算法保证了编译版本号和修正版本号能够持续的增长:每次编译后的版本号都比前一次的数字大。

The good news about this algorithm is that no two builds have exactly the same version. The bad news is that you need to record the build and revision numbers after the fact for the builds that do get released. My preference is to let the compiler generate the build and the revision numbers for me. By recording the exact build number generated when I release the assembly, I know the final version number. I never forget to change versions when I release a new assembly. There are exceptions, though. COM components register themselves every time you build them. Letting the compiler automatically generate build numbers creates new Registry entries every build, which quickly fills the Registry with useless information.

关于该算法的优势是:没有任何两次编译会具有相同的版本。不好的方面是:在程序被发布之后,你需要记录下编译版本号和修改版本号。我偏好的做法是:让编译器为我生成编译版本和修正版本。在发布程序集的时候,通过记录下精确的编译版本号数字,我可以知道最终的版本号。当我发布一个新的程序集的时候,我从不忘记修改版本号。但是也有例外。COM组件每次编译的时候对自己进行注册。如果让编译器自动生成编译版本号,那么在每次编译时都创建新的注册实体,无效信息很快就填充了注册表信息。

The last section contains information about strong names:

最后一部分包含强命名信息:

[assembly: AssemblyDelaySign(false)]

[assembly: AssemblyKeyFile("")]

[assembly: AssemblyKeyName("")]

Consider generating a strong name for all your assemblies. Strong-named assemblies are safe from tampering and provide the support for upgrading independently of the other assemblies in an application. However, you should avoid strong names on ASP.NET applications; locally installed strong-named assemblies don't load properly. Also, strong-named assemblies must be decorated with the AllowPartiallyTrustedCallers attribute, or they cannot be accessed by non-strongly-named assemblies (see Item 47).

考虑为所有的程序集生成强命名。强命名程序集对于篡改是安全的,同时为在应用程序里面独立于其他程序集进行更新提供了支持。然而,在ASP.NET应用程序中应该避免强命名;局部安装的强命名程序集不会被正确的加载。同时,强命名程序集必须使用AllowPartiallyTrustedCallers特性来装饰,否则,它们就不能被非强命名程序集访问(Item 47)

To upgrade a component in the field, the public and protected portions of the interface must be compatible at the IL level. That means no deleted methods, no modified parameters, and no changed return values. In short, none of the components that reference your component would need a recompile.

用这种方式更新一个组件时,接口的公共和保护部分在IL级别上应该是兼容的。这意味着没有删除的方法,没有修改的参数,没有修改过的返回值。简而言之,如果那样的话,引用你的组件的任何一个组件将会需要重编译。

You add configuration information to change the referenced assembly. The configuration information can be stored in three different locations, depending on the component you want to upgrade. To configure a single application, you create an application config file, located in the same directory as the application. To configure all applications that use a single component, you create a publisher policy file in the GAC. Finally, to make a global configuration change, you can edit the machine.config file, located in the Config directory under the .NET runtime (see Item 37).

通过添加配置信息来修改被引用的程序集。根据你要更新的组件的不同,配置信息可以被存储在三个地方。配置一个单独的应用程序的话,你可以创建一个应用程序的配置文件,放在和应用程序同样的目录下。要配置使用同一个单独组件的多个应用程序的话,你可以在GAC里面创建一个发布策略。最后,要想使全局配置发生变化的话,可以编辑machine.config文件,它位于.NET运行时的Config目录下。

In practice, you will never modify the machine.config file to upgrade your assemblies. This file contains information on a machine-wide basis. You will use the application config file to upgrade one application and then use a publisher policy file to upgrade a component shared by many applications.

实践中,你将永远不会通过修改machine.config文件来更新你的程序集。这个文件包含了整个机器范围的信息。你应该:使用应用程序的配置文件来更新一个应用程序,然后使用发布策略文件来更新被很多应用程序共享的组件。

The config files contain XML that describes the existing version and the upgraded version:

配置文件包含了描述现存的版本和被更新的版本的XML

<dependentAssembly>

  <assemblyIdentity name="MyAssembly"

    publicKeyToken="a0231341ddcfe32b" culture="neutral" />

  <bindingRedirect oldVersion="1.0.1444.20531"

    newVersion="1.1.1455.20221" />

</dependentAssembly>

 

You use the config file to identify the assembly, the old version, and its upgraded version. When you install an upgraded assembly, you update or create the appropriate config file, and the applications use the new version.

使用配置文件来定义程序集,旧版本,更新过的版本。当你安装一个更新过的程序集时,就需要更新或者创建一个合适的配置文件,那样的话,应用程序就会使用新版本了。

Think of your software as a collection of assemblies: You want to be able to upgrade them independently. To update software by updating one assembly at a time, you need to do some upfront work so that your first installation contains the necessary information to support upgrades.

将你的软件看做是一个程序集的集合:你希望它们能够被单独的更新。为了通过一次更新一个程序集的方式来更新软件,你需要做一些前期工作。那样的话,你的第一个安装的程序需要包含支持更新所需要的必须的信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值