在 C# 和 .NET 生态系统中,程序集(Assembly)是一个核心概念,它是管理和部署代码的基础单元。程序集是由一个或多个代码模块(如类、接口、结构等)组成的,具有以下重要特征:
- 独立性:程序集是一个自包含的单位,可以独立于其他程序集进行加载和运行。
- 版本控制:程序集包含版本信息,支持强名称和版本管理。
- 类型边界:程序集是类型的逻辑边界,定义了哪些类型可以访问哪些类型。
以下是对 C# 程序集的详细介绍:
程序集的组成部分
代码:
- 程序集可以包含一个或多个托管代码模块(通常是
.dll
或.exe
文件),这些代码模块是用 C# 等 .NET 语言编写的。 - 代码模块经过编译后,包含中间语言(IL),等待在运行时由 .NET CLR(公共语言运行时)解释和执行。
- 程序集可以包含一个或多个托管代码模块(通常是
元数据:
- 元数据是描述程序集内容的信息,包括类型定义、成员签名、属性等。
- 它允许 .NET 运行时在加载程序集时了解它的结构,并支持反射(reflection)。
清单(Manifest):
- 清单是程序集的描述文件,包含程序集的版本信息、文化信息、引用的其他程序集列表等。
- 清单确保程序集的唯一性和完整性。
资源:
- 程序集还可以包含非代码资源,如图像、字符串、XML 文件等,通常用于国际化或存储嵌入式资源。
程序集的类型
私有程序集(Private Assembly):
- 只能由与其放置在相同应用程序目录下的应用程序使用。
- 通常存储在应用程序的目录或子目录中,便于部署和管理。
共享程序集(Shared Assembly):
- 可以在多个应用程序之间共享。
- 通常需要强名称(Strong Name)签名,存储在全局程序集缓存(GAC)中。
- 共享程序集通过版本控制支持应用程序的安全更新和依赖管理。
创建和使用程序集
创建程序集
在 Visual Studio 中,创建一个新的类库项目(Class Library
)时,会生成一个 .dll
文件,这就是一个程序集。创建控制台应用程序或 Windows 应用程序时,生成的 .exe
文件也是一个程序集。
1 | // ExampleLibrary.cs |
编译后,ExampleLibrary
将成为一个程序集的一部分,通常是一个 .dll
文件。
引用程序集
在一个 C# 项目中,可以引用其他程序集来复用代码。引用可以通过 Visual Studio 的项目引用设置完成,或者在代码中使用 using
语句来导入命名空间。
1 | using ExampleLibrary; // 引用 ExampleLibrary 程序集 |
程序集的版本控制
程序集具有内置的版本控制功能,通过程序集版本(Assembly Version)来管理。版本号通常由四个部分组成:主版本号、次版本号、修订号和内部版本号。
1 | [ ] |
版本控制有助于在部署时管理程序集的不同版本,防止版本冲突和确保应用程序的兼容性。
程序集的强名称(Strong Name)
强名称是一种确保程序集唯一性和完整性的机制,尤其在共享程序集(如存储在 GAC 中)时非常重要。
- 强名称包括程序集的名称、版本号、公钥和数字签名。
- 使用
sn.exe
工具生成强名称密钥对,并使用它来签名程序集。
1 | sn -k MyKey.snk |
在项目的 AssemblyInfo.cs
文件中添加:
1 | [ ] |
全局程序集缓存(GAC)
GAC 是一个存储共享程序集的全局存储位置,支持多个版本的程序集共存,并解决了 DLL 冲突问题。
- 使用
gacutil
工具将程序集安装到 GAC。
1 | gacutil -i MyAssembly.dll |
使用反射访问程序集信息
C# 提供了强大的反射功能,允许在运行时动态加载和检查程序集及其内容。
1 | using System; |
总结
程序集是 C# 和 .NET 编程中一个重要的构建块,管理代码的编译、版本控制和分发。它们允许代码模块化、重用和封装,支持复杂应用程序的开发和维护。通过理解和有效使用程序集,开发者可以更好地组织和管理他们的代码库。