引用程序集复制的规则

时间:2011-08-27 14:00:55

标签: .net visual-studio

VS(msbuild?)在解决方案构建过程中遵循哪些规则?在哪些情况下,它会将间接引用的asemblies复制到输出文件夹,而不是?

4 个答案:

答案 0 :(得分:19)

我刚刚进行了一些实验,看起来任何间接引用的程序集都会被复制,该程序集的类型在另一个程序集中直接由代码引用。如果代码中没有任何内容,则不会。这是我的示例场景:

  • MainProgram:直接引用DirectAssembly的控制台应用程序。主要代码:

    var foo = new DirectAssembly.SampleClass();
    
  • DirectAssembly:直接引用IndirectAssembly的类库。包含SampleClass

    public class SampleClass
    {
        // Comment out this line to change the behaviour...
        IndirectAssembly.IndirectClass neverUsed = null;
    
        public SampleClass()
        {
            object x = Activator.CreateInstance("IndirectAssembly",
                                                "IndirectAssembly.IndirectClass");
    
        }
    }
    
  • IndirectAssembly:包含带有公共无参数构造函数的公共类IndirectClass

如上所述,它的工作原理是因为IndirectAssembly被复制到MainProgram的输出文件夹中。如果注释掉SampleClass中指示的行,则IndirectAssembly 被复制(即使它仍然是引用),并且代码将在执行时失败。

我不是说这些所有规则,但它们至少是一个开始......

答案 1 :(得分:5)

以前的答案没有解决一个微妙的问题,即引用的汇编是否在GAC中。

考虑一个引用程序集A的项目,而程序组A又依赖于程序集B和C.程序集C恰好已被某些"其他产品"安装到GAC中。我发现Visual Studio 2013将A和B而不是C复制到输出文件夹,因为C已经在GAC中。如果我然后在没有"其他产品"的机器上运行该应用程序。安装后,我收到运行时绑定失败。

我还注意到微软在这方面的文档似乎是错误的,至少在VS2013中是这样。

Managing Project References

  

如果部署的应用程序包含对GAC中注册的自定义组件的引用,则无论CopyLocal设置如何,该组件都不会随应用程序一起部署。在早期版本的Visual Studio中,您可以在引用上设置CopyLocal属性以确保部署了程序集。现在,您必须手动将程序集添加到\ Bin文件夹

我对VS2013的测试显示,与上述相反,CopyLocal = True 始终将直接引用的程序集复制到输出文件夹,无论它是否在GAC中。但间接引用的程序集只有在它们不在GAC中时才会被复制。

此行为意味着要确保使用您的应用程序部署间接引用的程序集,您应该使用CopyLocal = True(或手动复制它们)添加对它们的显式引用。请注意,默认情况下,如果程序集位于GAC中,则CopyLocal将设置为False。

答案 2 :(得分:2)

它应该复制所有递归引用。例如:

enter image description here

---编辑---

规则(至少在VS2010中)似乎如下:

  • 仅在实际使用时才复制间接引用。
  • 无论如何都会复制直接引用 - 即使实际未使用。

因此,如果要确保部署反射所需的程序集,请从根项目中引用它。

除了反思之外,似乎只需在项目层次结构的每个级别添加最小的引用集。

答案 3 :(得分:1)

我的经验是,它以递归方式复制所有直接引用的程序集 - 即代码中直接引用的任何内容,以及这些引用的任何内容。

不会引用代码中编译时未引用的任何内容。因此,不会复制仅在运行时解析的引用。这是因为,即使您可能确切地知道它所引用的内容,但是copmpiler却没有。无论是反射还是使用激活器来引用它(如已经给出的两个答案),因为在编译时,无法确定对象的实际类型。

项目中的引用指出应该解析代码引用的位置,但这就是全部 - 我认为证据是它们不会被复制 - 它全部基于编译时编码引用。

这就是为什么有些注入技术可以工作的原因之一,在编译或甚至部署之前无需完成引用的解析。