是“;复制本地”;可传递给项目引用

本文关键字:项目 可传递 引用 复制本 | 更新日期: 2023-09-27 18:25:18

Wrt。建议的欺骗:由于这里的问题与链接的问题相反,我宁愿认为这是而不是欺骗。

首先,我确实阅读了"复制本地"和项目参考的最佳实践是什么?(还有这个),无论如何我都必须尝试一下,但获得有关这方面的一般反馈似乎是必要的,因为关于这方面的文档很糟糕,而我只使用VS2010,也许他们在新版本中更改了一些内容,很高兴知道。

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

第三个,在阅读了建议的欺骗之后,但更重要的是@Albireo在这里给出了一个不错的答案,区分文件依赖关系似乎也很重要,其中依赖关系引用dll程序集文件和项目依存关系(即我所问的),其中依赖项引用项目并隐式引用该项目的输出文件。

不管怎样,情况是这样的,我认为有些奇怪,但仍然:

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

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

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

问题现在涉及可执行项目不直接引用但仅通过引用程序集传递的DLL:是否将通过另一程序集传递引用的仅的程序集复制到可执行文件的输出文件夹中,当第一个程序集上的"Copy Local"设置为true时?

示例:

  • x1.csproj(例如输出=x1/one.exe
    • 参考:dlA.csproj(例如输出=lib/a.dll)与Copy Local = *true*
    • (没有直接引用b.dll)
  • dlA.csproj(例如输出=lib/a.dll
    • 参考:dlB.csproj(例如输出=lib/b.dll)与Copy Local = **false**
    • (在c.dll上没有直接引用)
  • dlC.csproj(例如输出=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.ConsoleApplication
  • 我的解决方案。第一依赖性
  • MySolution.SecondDependency
  • MySolution.ThirdDependency
  • MySolution.FourthDependency

有了这个依赖链:

  • MySolution.ConsoleApplication
  • 我的解决方案。第一依赖性
    • MySolution.SecondDependency
      • MySolution.ThirdDependency
      • MySolution.FourthDependency

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

为什么会这样。

在过去,当我通过NuGet-AutoMapper添加到";深度依赖":添加AutoMapper会添加两个程序集引用AutoMapperAutoMapper.Net4,其中第二个程序集由第一个程序集在需要对.NET Framework 4引入的新集合对象执行某种操作时通过反射加载。由于第二个程序集是通过反射加载的,MSBuild认为它是未使用的,因此不必四处复制。

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

这有记录吗?

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

它非常直接,与复制本地无关。MSBuild在程序集的元数据中查找程序集的依赖项。你也可以,在程序集上运行ildasm.exe,然后双击Manifest。一定要尝试一下以获得洞察力。您将看到.assembly指令。编译器在生成程序集时插入的程序集,将只列出代码中实际使用的引用程序集。

如果MSBuild能在同一目录中找到这样的程序集,它将自动复制它。如果不能,它将静默地跳过复制。

由此可以推断出故障模式。它无法复制非托管DLL,它们不会出现在元数据中。它无法通过Assembly.Load/From()复制您间接依赖的程序集,它们也不会出现在元数据中。它无法复制尚未生成的程序集,这是一个生成顺序问题。并且它无法复制"复制本地"属性设置为False的程序集。如果GAC中存在程序集,则这通常是一个有效的选择,不需要副本。

对于这种需要帮助的情况,XCOPY在构建后事件中完成任务。