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

Mar*_* Ba 30 .net c# msbuild copy-local visual-studio

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

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

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

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

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

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

该DLL组件已经Copy Local设置false了自己的项目引用,因为它们都建立在相同的输出目录.

2个可执行项目已设置Copy Localtrue所有他们直接引用的DLL组件项目引用,这样的DLL将被复制到/x1 /x2分别.

现在的问题是.到被DLL文件不能直接通过一个可执行的项目引用,但传递地通过引用的程序集:请问组件,这是只有通过其他组件引用传递性,被复制到输出文件夹的可执行文件的,当"复制本地" 设定为第一次装配时是真的吗?

例:

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

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


而且,是的,我试过了.并且,是的,它似乎有效,但我还没有足够努力地探索它,无论如何可能还有一些我可能错过的东西.(而且还有问题.任何官方文档.)

Alb*_*reo 27

它似乎也很重要,区分文件依赖项,其中依赖项引用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输出目录下会存在的DLL文件MySolution.FirstDependency,MySolution.SecondDependencyMySolution.ThirdDependency但没有DLL MySolution.FourthDependency.

为什么会这样?当MSBuild构建时,MySolution.SecondDependency它注意到声明了一个依赖项MySolution.FourthDependency,但由于它无法MySolution.FourthDependencyMySolution.SecondDependency代码中找到任何类型元素的任何用法,因此它决定执行一些"优化"并MySolution.FourthDependency从输出中省略汇编.

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

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

这是在某处记录的吗?

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


Han*_*ant 19

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

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

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

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