如何识别“引用程序集”?

9
许多.NET程序集都提供仅包含元数据而剥离了实际代码的参考版本
例如,我可以在我的计算机上找到 System.Core.dll 的几个位置,其中两个如下:
  • C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\System.Core.dll 大小:276 KB
  • C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll 大小:1291 KB
第一个仅包含元数据,将其加载到默认加载上下文中会抛出 BadImageFormat 异常。

System.BadImageFormatException: Could not load file or assembly 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. 不应该为执行加载参考程序集。它们只能在反射加载器上下文中加载。

给定一个程序集的路径,能否找出它是否为“引用程序集”?

我可以检查路径中是否包含关键字“Reference Assemblies”,但这样是hacky的,如果程序集被复制到不同的位置那么这种方法就不起作用了。 如果有必要,我可以在反射上下文中首先加载程序集。


微软似乎没有详细解释在生成引用程序集时从完整程序集中删除了什么内容。为什么需要对其进行检查?除了在开发人员机器上,很少会看到引用程序集。 - Lex Li
你目前是如何加载程序集从而产生 BadImageFormatException 异常的? - Michael Liu
1
很难猜到你是怎么陷入这个困境的,IDE肯定不会出错。而且程序集在GAC中,所以你总是会加载正确的程序集。否则很容易发现你加载了错误的程序集,异常信息非常明显。水晶球显示你正在使用Assembly.LoadFile()方法,这个方法名虽然很吸引人,但99.9%的情况下使用都是错误的。请改用Load方法。 - Hans Passant
1个回答

5

我在CoreCLR中找到了这段代码dotnet/coreclr/.../pefile.inl,它通过System.Runtime.CompilerServices.ReferenceAssemblyAttribute来识别引用程序集:

if (mdImport->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly),
                                       g_ReferenceAssemblyAttribute,
                                       NULL,
                                       NULL) == S_OK) {
    ThrowHR(COR_E_LOADING_REFERENCE_ASSEMBLY, BFA_REFERENCE_ASSEMBLY);
}

我认为完整的CLR也会做同样的事情。
我还没有尝试过,但你可以将你的程序集加载到反射上下文中,然后检查它是否有一个ReferenceAssemblyAttribute。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接