如何识别重复的组件?

时间:2009-11-16 17:36:26

标签: .net reflection

虽然我正在查看有关MEF的一些问题,但我偶然发现了this particular answer一个问题。这让我对此感到疑惑,因为我从来没有尝试过这样的事情,但可以看出它在这个问题的场景中非常有效。

情境: 如果你有一个名为不同的各种.Net程序集的目录,你怎么能识别可能相同但重命名的目录(即MyAssembly.dll和MyAssembly.dll的副本)?

我能想到以下几点:

  1. 检查文件大小(应该相同)

  2. 检查装配版本号

  3. 使用Reflection循环组装并尝试找出任何差异。

  4. 还有其他/更简单的方法来解决这个问题吗?是否有其他标准可以确定2个不同名称的DLL实际上是否是相同的编译汇编?

3 个答案:

答案 0 :(得分:1)

我将首先使用第1点和第2点进行简单快速检查,即检查文件大小和程序集版本号。如果他们完全不同,那就完成了。

如果没有,请保留具有相同文件大小/版本的文件并计算其MD5 / SHA1 /您喜欢的任何哈希值。如果哈希是相同的,那么你肯定会出现两次相同的程序集。由于程序集通常不是很大(最多只有几兆字节),因此哈希计算应该足够快。

答案 1 :(得分:1)

起初我以为您可以使用EqualsReferenceEquals来执行此操作,但这证明太容易出错。例如,如果您使用Assembly.LoadFile,则无法使用此功能。

使用nUnit,我做了以下测试,这些测试有点基础,但是给你一些东西。加载类型的奇怪方法是必要的(参见MSDN)。我假设您知道如何进行“快速测试”,以防您想要检查二进制相等等(请参阅下面的PS)。

Assembly asm1 = Assembly.LoadFile(@"someDebugAssembly.dll");
Assembly asm2 = Assembly.LoadFile(@"someReleaseAssembly.dll");

// load all the types (the double try/catch is on purpose)
Type[] types1 = null
Type[] types2 = null;
try
{
    types1 = asm1.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
    types1 = e.Types;
}
try 
{
    types2 = asm1.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
    types2 = e.Types;
}

// same length
Assert.AreEqual(types1.Length, types2.Length);

// check each type
IEnumerator types1Enumerator =  types1.GetEnumerator();
types1Enumerator.Reset();
foreach (Type t in types2)
{
    types1Enumerator.MoveNext();
    Assert.AreEqual(types1Enumerator.Current, t);
}

关于代码的注释:这种比较方法在包含相同类型时将两个程序集视为相等。这意味着不考虑调试和发布版本或不同版本。使用asm1.GetName()及其属性(再次:不要使用Equals!)来比较各个字符串(版本,全名等)。

PS:定义两个相等组件的构成是有趣的,即:

  1. 他们是二进制相等的
  2. 版本和完全限定名称相等
  3. 强名称相等
  4. 所有类型,深度比较,具有相同的签名
  5. 取决于您选择的内容,两个完全不同的程序集(即调试版本与发布版本)可以相同。这实际上取决于你想要比较的方式。

    更新: 更正了之前的错误并添加了代码示例

答案 2 :(得分:1)

您还可以使用旧的 comp 命令行程序:

c:\tests> comp one.dll two.dll
Comparing one.dll and two.dll...
Files compare OK

<击> 更新:更好。下载Windows XP Service Pack 2 support tools,安装它(选择完成安装)。然后转到“运行命令”对话框并键入 dupfinder 。将它指向您希望您开始查看该路径及其子文件夹中所有重复项的文件夹。