项目参考的“复制本地”是否可传递?

WRT。 拟议的欺骗:由于这里的问题暗示了相关的问题 ,我宁愿认为这不是一个骗局。

首先 ,我确实阅读了“复制本地”和项目参考的最佳实践是什么? (也是这个 )我无论如何都要尝试这个,但是得到一般的反馈似乎是必要的,因为关于这个东西的文档是可怕的,我只是在VS2010上,也许他们改变了新版本的东西,这将是很高兴知道。

其次 ,我只对这个问题的项目引用感兴趣,因为我读过GAC的程序集处理方式不同而GAC与我的问题无关。

第三 ,在阅读了建议的欺骗之后,但更多的是@Albireo这里的好答案 ,它似乎也很重要,区分文件依赖,其中依赖引用dll汇编文件和项目依赖(即我问的是什么) about),其中依赖项引用项目并隐式引用该项目的输出文件。

无论如何,这是我认为有点奇怪的情况,但仍然:

  • 2个C#可执行项目
  • n C#dll组装项目
  • 这两个可执行文件具有不同的输出目录,因为它们将单独部署,这样它们在开发人员计算机上也是独立的
  • 2个可执行文件依赖于某些DLL程序集(可能相互依赖)
  • 有三个输出目录:
    • /x1表示可执行1项目
    • /x2表示可执行文件2项目
    • /lib用于所有dll程序集

DLL程序集的所有项目引用都Copy Local设置为false ,因为它们都构建到同一个输出目录。

对于它们直接引用的所有DLL程序集项目引用,2个可执行项目已将Copy Local设置为true ,以便将DLL分别复制到/x1 /x2

现在的问题是。 到可执行项目没有直接引用的DLL,但只能传递给引用的程序集:当“Copy Local”设置为“Copy Local”时,将通过另一个程序集传递的程序集复制到可执行文件的输出文件夹中第一次assembly时是真的吗?

例:

  • x1.csproj (egOutput = x1/one.exe
    • 参考: dlA.csproj (例如Output = lib/a.dll ), Copy Local = *true*
    • (没有直接引用b.dll)
  • dlA.csproj (例如Output = lib/a.dll
    • 参考: dlB.csproj (例如Output = lib/b.dll ), Copy Local = **false**
    • (没有直接引用c.dll)
  • dlC.csproj (例如Output = lib/c.dll
    • (没有进一步的相关参考)

因此,我们有一个逻辑依赖的one.exe -> a.dll -> b.dll -> c.dll ,其中只有a.dll明显被复制到one.exe的输出目录。 另外两个dll是否也会被复制到输出目录中? 这是在某处记录的吗?


而且,是的,我试过了。 并且,是的,它似乎工作,但我还没有足够努力,无论如何可能还有更多我可能错过的东西。 (而且还有问题。任何官方文档。)

它似乎也很重要,区分文件依赖项,其中依赖项引用dll程序集文件和项目依赖项(即我要问的内容),依赖项引用项目,隐式引用该项目的输出文件。

不是,不是。

MSBuild并不关心引用是指向解决方案中的另一个项目还是DLL。

如果ProjectA依赖于ProjectB来构建ProjectA ProjectB必须已经构建(并且是最新的),那么MSBuild将提取其DLL(而不是其C#代码)并将其链接到ProjectA

为方便起见,添加项目引用而不是DLL是“语法糖”:MSBuild知道它必须选择引用项目的输出,无论输出是什么。

否则,您必须手动预构建依赖项,找到其DLL并将其链接到项目,每当您切换构建配置,移动或重命名时重复该过程。 不太实际。

另外两个dll是否也会被复制到输出目录中?

如果直接从引用程序集的项目中使用依赖项中的任何类型的元素,则将复制该引用。

一个例子可能是这个解决方案布局:

  • MySolution
    • MySolution.ConsoleApplication
    • MySolution.FirstDependency
    • MySolution.SecondDependency
    • MySolution.ThirdDependency
    • MySolution.FourthDependency

有了这个依赖链:

  • MySolution.ConsoleApplication
    • MySolution.FirstDependency
      • MySolution.SecondDependency
        • MySolution.ThirdDependency
        • MySolution.FourthDependency

如果您构建此解决方案,您会注意到在MySolution.ConsoleApplication输出目录中将有MySolution.FirstDependencyMySolution.SecondDependencyMySolution.ThirdDependency DLL,但没有MySolution.FourthDependency DLL。

为什么会这样? 当MSBuild构建MySolution.SecondDependency它注意到向MySolution.FourthDependency声明了一个依赖MySolution.FourthDependency ,但由于它无法在MySolution.SecondDependency代码中找到MySolution.FourthDependency中任何类型元素的任何用法,因此它决定执行一些“优化”和从输出中省略MySolution.FourthDependency程序集

当我通过NuGet AutoMapper添加到“深度依赖”时,同样的问题让我感到困惑:添加AutoMapper会添加两个程序集引用, AutoMapperAutoMapper.Net4 ,其中第二个程序集在需要执行时通过第一个reflection加载对.NET Framework 4引入的新集合对象的某种操作。由于第二个程序集是通过reflection加载的,因此MSBuild认为它是未使用的,并且不需要复制它。

所以, 是的 ,只要您直接使用它们而不是通过reflection,它们就会被复制

这是在某处记录的吗?

这种行为似乎是MSBuild的一个“特性”,当我遇到这个问题时,我设法找到了一些来自微软的人的博客文章,但我现在再也找不到了。

它很直接,与Copy Local没有任何关系。 MSBuild查看程序集的元数据以查看程序集的依赖项。 那么,你可以在程序集上运行ildasm.exe并双击Manifest。 一定要尝试这一点来获得洞察力。 你会看到.assembly指令。 在构建程序集时由编译器插入,只列出您在代码中实际使用的引用程序集。

如果MSBuild可以在同一目录中找到这样的程序集,那么它将自动复制它。 如果没有,那么它将默默地跳过副本。

由此,您可以推断出故障模式。 它无法复制非托管DLL,它们不会出现在元数据中。 它不能通过Assembly.Load / From()复制您具有间接依赖关系的程序集,它们也不会出现在元数据中。 它无法复制尚未构建的程序集,即构建顺序问题。 并且它无法复制其Copy Local属性设置为False的程序集。 如果GAC中存在程序集,通常只有一个有效的选择,不需要复制。

对于这种情况,您需要提供帮助,XCOPY在构建后的事件中完成工作。