C# 基础系列--程序集二
在上一篇中,我们对程序集做了几个实验,发现是如此的糟糕。原来我们不懂程序集。
那我们从头来学习程序集。找了msdn发现http://msdn.microsoft.com/zh-cn/library/k3677y81(v=vs.100) 这里是这样说的:
程序集构成了基于 .NET 的应用程序的部署、版本控制、重用、激活范围和安全权限的基本单元。程序集以可执行 (.exe) 文件或动态链接库 (.dll) 文件的形式出现,是 .NET Framework 的生成块。它们向公共语言运行库提供了解类型实现所需要的信息。可以将程序集看成是构成逻辑功能单元并为一起工作而生成的类型和资源的集合。
我突然想说,msdn的解释一如既往的简洁明了。。。翻阅了下,我的C#高级编程第七版。解释一模一样。
程序集可以分为,公有程序集和私有程序集。微软给我们用framework的提供的System之类的就是公有程序集,私有程序集可以说是我们新建的类库吧。 为什么会有这个区分,因为一般来说一个程序集只能被一个进程域加载,如果要多个进程域加载同一个程序集,那么只有把程序集变成公有程序集。我们写的dll也是可以加入公有程序集的(但是必须是有强名)。很简单的,自己baidu下就可以找到。有一个很简单的区分是不是公有程序集的方法,如果你引用这个dll。这个dll没有被复制到bin目录,那他就是公有程序集(微软提供和自己加入公有程序集)---------------2012年7月13日 星期五修改
上一遍中,我们建立了两个类库,当然我们也可以建立N个类库。那么就有一个问题,名字是我们取得,那不可以避免的就是同名的问题,那么就会出现上一遍中的问题。继续 翻msdn,发现无果,C#高级编程这本书还是不错的(建议大家可以买一本,148快也不贵),在书中提到了一句话:程序集必须是唯一的,因此,必须有一个唯一的名称(称为强名)。又一个专业名称的出现,如果细心的朋友,应该在mdsn中看到具有强名称的程序集
强名称是由程序集的标识加上公钥和数字签名组成的。其中,程序集的标识包括简单文本名称、版本号和区域性信息(如果提供的话)。 强名称是使用相应的私钥,通过程序集文件(包含程序集清单的文件,并因而也包含构成该程序集的所有文件的名称和散列)生成的。 Microsoft® Visual Studio® .NET 和 Windows 软件开发包 (SDK) 中提供的其他开发工具能够向一个程序集分配多个强名称。 强名称相同的程序集应该是相同的。 通过签发具有强名称的程序集,您可以确保名称的全局唯一性。 强名称还特别满足以下要求: 强名称依赖于唯一的密钥对来确保名称的唯一性。 任何人都不会生成与您生成的相同的程序集名称,因为用一个私钥生成的程序集的名称与用其他私钥生成的程序集的名称不相同。 强名称保护程序集的版本沿袭。 强名称可以确保没有人能够生成您的程序集的后续版本。 用户可以确信,他们所加载的程序集的版本出自创建该版本(应用程序是用该版本生成的)的同一个发行者。 强名称提供可靠的完整性检查。 通过 .NET Framework 安全检查后,即可确信程序集的内容在生成后未被更改过。 但请注意,强名称中或强名称本身并不暗含信任级别,例如由数字签名和支持证书提供的信任。 在引用具有强名称的程序集时,您应该能够从中受益,例如版本控制和命名保护。 如果此具有强名称的程序集以后引用了具有简单名称的程序集(后者没有这些好处),则您将失去使用具有强名称的程序集所带来的好处,并依旧会产生 DLL 冲突。 因此,具有强名称的程序集只能引用其他具有强名称的程序集。
我们来浓缩下:程序集名称+版本+公共密钥=强名
AssemblyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 这个可以理解为强名。
我们来试试创建下他的公有密钥吧。本人 比较来,还是图形化吧,这样简单傻瓜
简单吧。F6。。。
错误 1 程序集生成失败 -- 引用的程序集“AssemblyLibrary”没有强名称 AssemblyLibrary。。发现AssemblyLibrary2没有给他一个签名,又不是大明星,居然要签名。
全部签名完。
F6,编译通过。
F5:未能加载文件或程序集“AssemblyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=525b694786e1bcdf”或它的某一个依赖项。系统找不到指定的文件。
虽然错误了,但是我们发现比之前的报错信息,可以发现PublicKeyToken不再是null而是由具体的值。有空的朋友可以用ILspy来反编译下,可以发现两个AssemblyLibrary的dll的
PublicKeyToken值都是不一样的。如果两个dll用同一个密钥,理论上应该是一样的。试了下,果然一样。突发奇想,如果有 同一个密钥,那么会不会认为可以运行通
过了呢??
实验一把。
static void Main(string[] args) { PulClass pu = new PulClass(); pu.ID = 1; //pu.SHOW = null; Console.WriteLine(pu.ID.ToString()); Console.Read(); }
F5:应该打印出了 1 !!!!!
那么pu.SHOW = null;取消注释会是这样呢,会不会奇迹出现。很遗憾,我们不是刘谦,没有奇迹。
错误 5 现用语言不支持“AssemblyLibrary.PulClass.SHOW” d:\documents\visual studio 2010\Projects\ConsolTest\ConsolTest\Program.cs 15 16 ConsolTest
为什么开始我们是可以 编译通过并可以执行,后一个却是失败。那个我刚刚这个公式:程序集名称+版本+公共密钥=强名是错误?还是怎么回事。迷糊了。打开ConsolTest的bin目录也只有 一个dll。
Proprerties有个AssemblyInfo.cs的文件,这里包含了程序集的信息。那如果我把这两个文件的内容变为一致会怎么样呢?是不是就认为是同一个程序集呢。
…………过程省略pu.SHOW = null;还是编译不过
看来,微软在编译的时候做了很多东西。在用ilspy看看,两个AssemblyLibrary.dll 的信息
using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; [assembly: AssemblyVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")] [assembly: AssemblyDescription("")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyProduct("AssemblyLibrary")] [assembly: AssemblyCopyright("Copyright © 2012")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("AssemblyLibrary")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8b29312c-6956-44ff-af8c-b5d5fa0da22a")] [assembly: AssemblyFileVersion("1.0.0.0")]
using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyProduct("AssemblyLibrary")] [assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")] [assembly: AssemblyTitle("AssemblyLibrary")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: Guid("8b29312c-6956-44ff-af8c-b5d5fa0da22a")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: AssemblyCopyright("Copyright © 2012")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: CompilationRelaxations(8)]
很明显这里面的程序集信息是不一样的。看来 程序集名称+版本+公共密钥=强名这个公式是没有问题的。
现在的实验可以给我们一个这样的结论:
程序集的名称必须是唯一的。就算你建立了两个类库,取相同的程序集名称,一样的程序集信息(AssemblyInfo.cs),一样的密钥,在微软的编译过程中会生成不一样的程序集信息。
理论上来说,你是不可能有一样的(AssemblyInfo.cs),因为这个文件有个GUID
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("8b29312c-6956-44ff-af8c-b5d5fa0da22a")]
GUID是全球唯一的
下一遍对程序集的其他信息进行 阐述和实验。
2012年7月12日 星期四修改