如何创建和使用仅限.NET元数据的“参考组件”?

从3.0版开始,.NET在C:\ Program Files \ Reference Assemblies \ Microsoft ….下安装了许多不同的“引用程序集”,以支持不同的配置文件(比如.NET 3.5客户端配置文件,Silverlight配置文件)。 其中每个都是一个正确的.NET程序集,只包含元数据 – 没有IL代码 – 每个程序集都标有ReferenceAssemblyAttribute 。 元数据仅限于适用的配置文件下可用的那些类型和成员 – 这就是intellisense显示一组受限制的类型和成员的方式。 在运行时不使用引用程序集。

我从这篇博文中了解到了一些情况。

我想为我的库创建和使用这样的引用程序集。

  1. 如何创建仅元数据的程序集 – 是否有一些编译器标志或ildasm后处理器?
  2. 是否存在控制将哪些类型导出到不同“配置文件”的属性?
  3. 如何在运行时引用程序集解析 – 如果我的应用程序目录中存在引用程序集而不是’真正的’程序集,而不是GAC中的引用程序集将会探测继续并且我的AssemblyResolve事件触发,以便我可以提供在运行时实际组装?

任何有关我可以了解更多信息的想法或指示都将不胜感激。

更新:环顾一下,我看到.NET 3.0’引用程序集’似乎确实有一些代码,并且引用程序集属性仅在.NET 4.0中添加。 因此,新运行时的行为可能会有所改变。

为什么? 对于我的Excel-DNA( http://exceldna.codeplex.com )加载项库,我通过将引用的程序集作为资源打包到.xll文件中来创建单文件.xll加载项。 打包的程序集包括用户的加载项代码,以及Excel-DNA托管库(可能由用户的程序集引用)。

这听起来相当复杂,但大部分时间都运行得非常好 – 加载项是一个小文件,所以没有安装分发问题。 由于版本不同,我遇到(不是意料之外的)问题 – 如果Excel-DNA托管库的旧版本作为文件,运行时将加载而不是打包的(我永远不会有机会干扰加载)。

我希望为我的Excel-DNA托管部分制作一个参考汇编,用户在编译它们的加载项时可以指向它。 但是如果他们在运行时错误地拥有了这个程序集的一个版本,那么运行时应该无法加载它,并让我有机会从资源加载真正的程序集。

要创建引用程序集,可以将此行添加到AssemblyInfo.cs文件中:

 [assembly: ReferenceAssembly] 

要加载其他人,可以像往常一样从VisualStudio项目引用中引用它们,或者在运行时使用以下命令动态引用它们:

Assembly.ReflectionOnlyLoad()

要么

Assembly.ReflectionOnlyLoadFrom()


如果您使用VisualStudio添加了对元数据/引用程序集的引用,那么智能感知和构建项目将正常工作,但是如果您尝试针对其中一个执行应用程序,则会出现错误:

System.BadImageFormatException:无法加载引用程序集以供执行。

因此,期望在运行时,您将替换具有相同元数据签名的实际程序集。

如果使用Assembly.ReflectionOnlyLoad()动态加载了一个程序集,那么你只能对它进行所有的reflection操作(读取类型,方法,属性,属性等,但不能动态调用它们中的任何一个)。


我很好奇你的用例是什么用于创建仅元数据的程序集。 我以前从来没有这么做过,并且很想知道你是否找到了一些有趣的用途……

如果您仍然对这种可能性感兴趣,我已经基于Mono.Cecil创建了一个il-repack项目的分支,它接受一个“/ meta”命令行参数来为公共和受保护类型生成仅元数据的程序集。

https://github.com/KarimLUCCIN/il-repack/tree/xna

(我在完整的XNA框架及其工作方面尝试过它…)

是的,这是.NET 4.0的新function。 我很确定这是为了避免.NET 2.0 Service Pack中令人讨厌的版本控制问题。 最好的例子是WaitHandle.WaitOne(int)重载,在SP2中添加并记录。 一个流行的重载,因为它避免了在WaitOne(int,bool)重载中猜测* exitContext的正确值。问题是,程序在2.0版本比SP2运行时发生爆炸。不是很开心诊断要么。隔离参考组件可确保不再发生这种情况。

认为这些引用程序集是通过从已编译程序集的副本开始创建的(就像在以前的版本中完成的那样)并通过从程序集中剥离IL的工具来运行它们。 但是,我们无法使用该工具,bin / netfx 4.0工具Windows 7.1 SDK子目录中没有任何内容可以执行此操作。 不完全是经常使用的工具,因此它可能不是生产质量:)

您可能会对Cecil图书馆(来自Mono)感到满意; 我认为实现允许ILMergefunction,它也可以只编写元数据组件。

我扫描了代码库(文档很稀疏),但还没有发现任何明显的线索……

YYMV