元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
C#运行时环境
▶
CLR基础架构
CLR组成与生命周期
托管代码执行流程
应用程序域机制
▶
程序集体系
程序集元数据结构
强名称与版本控制
动态程序集生成
▶
类型系统
CTS核心规范
值类型与引用类型
类型加载与验证
▶
编译与执行
▶
编译过程
从源代码到IL
JIT编译原理
AOT编译机制
▶
执行引擎
方法表结构
栈帧与调用约定
尾调用优化
▶
IL深入解析
IL指令集解析
元数据表结构
调试符号处理
▶
内存管理
▶
垃圾回收
分代回收算法
终结器机制
GC句柄类型
▶
内存模型
托管堆结构
栈内存管理
大对象堆优化
▶
内存优化
内存碎片处理
ArrayPool机制
Span内存视图
发布时间:
2025-03-24 10:17
↑
☰
# 强名称与版本控制 ## 强名称概述 强名称(Strong Name)是.NET平台中用于唯一标识程序集的机制。它通过结合程序集的名称、版本号、文化信息和公钥令牌来确保程序集的唯一性和完整性。本文将详细介绍强名称的实现机制和版本控制策略。 ## 强名称的组成 ### 1. 密钥对生成 ```csharp // 使用sn.exe工具生成密钥对 // sn -k MyKey.snk // 在代码中使用密钥文件 [assembly: AssemblyKeyFile("MyKey.snk")] ``` 强名称的主要组成部分: - 程序集名称 - 版本号 - 文化信息 - 公钥令牌 - 数字签名 ### 2. 签名过程 ```csharp // 程序集签名示例 [assembly: AssemblyTitle("MyLibrary")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyCulture("")] [assembly: AssemblyKeyFile("MyKey.snk")] public class SignedLibrary { public void DemonstrateSignature() { // 获取当前程序集 Assembly assembly = Assembly.GetExecutingAssembly(); // 验证是否已签名 AssemblyName name = assembly.GetName(); byte[] publicKey = name.GetPublicKey(); if (publicKey != null && publicKey.Length > 0) { Console.WriteLine("程序集已签名"); } } } ``` ## 版本控制 ### 1. 版本号格式 ```csharp // 版本号定义 [assembly: AssemblyVersion("1.2.3.4")] [assembly: AssemblyFileVersion("1.2.3.4")] /* 版本号组成: - 主版本号(1):重大更改 - 次版本号(2):新功能添加 - 内部版本号(3):Bug修复 - 修订号(4):小改动 */ ``` ### 2. 版本策略 ```csharp // 版本控制示例 public class VersionControl { public void DemonstrateVersioning() { // 加载特定版本的程序集 AssemblyName name = new AssemblyName { Name = "MyLibrary", Version = new Version(1, 0, 0, 0) }; try { Assembly.Load(name); } catch (FileNotFoundException ex) { Console.WriteLine($"无法找到指定版本: {ex.Message}"); } } } ``` ### 3. 绑定重定向 ```xml <!-- app.config 或 web.config 中的绑定重定向 --> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="MyLibrary" publicKeyToken="32ab4ba45e0a69a1" culture="neutral" /> <bindingRedirect oldVersion="1.0.0.0-1.9.9.9" newVersion="2.0.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration> ``` ## 延迟签名 ### 1. 配置延迟签名 ```csharp // 启用延迟签名 [assembly: AssemblyDelaySign(true)] [assembly: AssemblyKeyFile("PublicKey.snk")] public class DelaySignExample { public void ConfigureDelaySign() { // 验证延迟签名状态 Assembly assembly = Assembly.GetExecutingAssembly(); AssemblyName name = assembly.GetName(); // 检查是否只有公钥 byte[] publicKey = name.GetPublicKey(); byte[] publicKeyToken = name.GetPublicKeyToken(); Console.WriteLine($"公钥长度: {publicKey?.Length ?? 0}"); Console.WriteLine($"公钥令牌: {BitConverter.ToString(publicKeyToken ?? new byte[0])}"); } } ``` ### 2. 完成签名 ```powershell # 使用sn.exe完成签名 # sn -R Assembly.dll PrivateKey.snk ``` ## 全局程序集缓存(GAC) ### 1. GAC注册 ```csharp public class GacExample { public void DemonstrateGac() { // 获取GAC中的程序集 string gacPath = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.Windows), "assembly"); if (Directory.Exists(gacPath)) { // 列出GAC中的程序集 var files = Directory.GetFiles(gacPath, "*.dll", SearchOption.AllDirectories); foreach (var file in files) { try { AssemblyName name = AssemblyName.GetAssemblyName(file); Console.WriteLine($"程序集: {name.FullName}"); } catch { // 忽略无效的程序集 } } } } } ``` ### 2. 程序集解析 ```csharp public class AssemblyResolver { public void SetupResolver() { // 注册程序集解析事件 AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { AssemblyName name = new AssemblyName(args.Name); // 实现自定义的程序集加载逻辑 string assemblyPath = Path.Combine( AppDomain.CurrentDomain.BaseDirectory, $"{name.Name}.dll"); if (File.Exists(assemblyPath)) { return Assembly.LoadFrom(assemblyPath); } return null; }; } } ``` ## 最佳实践 ### 1. 版本管理策略 ```csharp // 版本管理示例 public class VersioningBestPractices { public void DemonstrateVersioning() { // 使用语义化版本 Version version = new Version(1, 0, 0, 0); // 版本比较 Version otherVersion = new Version(1, 1, 0, 0); if (version < otherVersion) { Console.WriteLine("需要更新"); } // 版本范围检查 VersionRange range = new VersionRange( new Version(1, 0, 0, 0), new Version(2, 0, 0, 0)); if (range.IsInRange(version)) { Console.WriteLine("版本兼容"); } } } public class VersionRange { public Version MinVersion { get; } public Version MaxVersion { get; } public VersionRange(Version min, Version max) { MinVersion = min; MaxVersion = max; } public bool IsInRange(Version version) { return version >= MinVersion && version < MaxVersion; } } ``` ### 2. 签名安全性 ```csharp public class SigningSecurity { public void SecureSigningPractices() { // 保护密钥文件 string keyFile = "MyKey.snk"; if (File.Exists(keyFile)) { // 设置适当的文件权限 var security = File.GetAccessControl(keyFile); security.SetAccessRule( new FileSystemAccessRule( "Users", FileSystemRights.Read, AccessControlType.Allow)); File.SetAccessControl(keyFile, security); } // 验证程序集签名 Assembly assembly = Assembly.GetExecutingAssembly(); try { byte[] publicKeyToken = assembly.GetName().GetPublicKeyToken(); if (publicKeyToken != null && publicKeyToken.Length > 0) { // 执行额外的验证 ValidateAssembly(assembly); } } catch (Exception ex) { Console.WriteLine($"签名验证失败: {ex.Message}"); } } private void ValidateAssembly(Assembly assembly) { // 实现自定义的验证逻辑 // 例如:检查证书吊销列表 // 验证时间戳 // 检查信任链 } } ``` ## 总结 强名称和版本控制是.NET平台中确保程序集完整性和管理依赖关系的重要机制。通过合理使用这些特性,我们可以: 1. 确保程序集的唯一性和完整性 2. 实现可靠的版本控制 3. 管理程序集依赖关系 4. 支持并行程序集部署 在实际开发中,应该根据项目需求选择适当的版本控制策略,并确保密钥的安全管理。同时,也要注意版本兼容性问题,合理使用绑定重定向来处理版本冲突。