gpt4 book ai didi

c# - "Copy Local"和项目引用的最佳实践是什么?

转载 作者:IT王子 更新时间:2023-10-29 03:31:17 26 4
gpt4 key购买 nike

我有一个很大的 c# 解决方案文件(约 100 个项目),我正在努力缩短构建时间。我认为“复制本地”在很多情况下对我们来说都是浪费,但我想知道最佳实践。

在我们的 .sln 中,我们的应用程序 A 依赖于程序集 B,而程序集 B 又依赖于程序集 C。在我们的例子中,有几十个“B”和少数“C”。因为这些都包含在 .sln 中,所以我们使用项目引用。当前所有程序集都构建到 $(SolutionDir)/Debug(或 Release)中。

默认情况下,Visual Studio 将这些项目引用标记为“复制本地”,这会导致每个“C”被复制到 $(SolutionDir)/Debug 中,每构建一个“B”。这似乎很浪费。如果我只是关闭“复制本地”会出现什么问题?拥有大型系统的其他人做什么?

跟进:

很多回复建议将构建分解成更小的 .sln 文件...在上面的示例中,我将首先构建基础类“C”,然后是大部分模块“B”,然后是一些应用程序,“A”。在这个模型中,我需要从 B 对 C 进行非项目引用。我遇到的问题是“调试”或“发布”被烘焙到提示路径中,我最终构建了“B”的发布版本针对“C”的调试版本。

对于那些将构建分成多个 .sln 文件的人,您如何解决这个问题?

最佳答案

在之前的项目中,我使用了一个带有项目引用的大型解决方案,但也遇到了性能问题。解决方案分为三部分:

  1. 始终将 Copy Local 属性设置为 false 并通过自定义 msbuild 步骤强制执行此操作

  2. 将每个项目的输出目录设置为同一目录(最好是相对于$(SolutionDir)

  3. 框架附带的默认 cs 目标计算要复制到当前正在构建的项目的输出目录的引用集。由于这需要在“引用”关系下计算传递闭包,因此这可能会变得非常。我的解决方法是在导入 Microsoft .CSharp.目标。导致每个项目文件如下所示:

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
    ... snip ...
    </ItemGroup>
    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    <Import Project="[relative path to Common.targets]" />
    <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
    Other similar extension points exist, see Microsoft.Common.targets.
    <Target Name="BeforeBuild">
    </Target>
    <Target Name="AfterBuild">
    </Target>
    -->
    </Project>

这将我们在给定时间的构建时间从几个小时(主要是由于内存限制)减少到几分钟。

可以通过从 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common 复制第 2,438–2,450 和 2,474–2,524 行来创建重新定义的 GetCopyToOutputDirectoryItems。目标Common.targets

为了完整性,生成的目标定义将变为:

<!-- This is a modified version of the Microsoft.Common.targets
version of this target it does not include transitively
referenced projects. Since this leads to enormous memory
consumption and is not needed since we use the single
output directory strategy.
============================================================
GetCopyToOutputDirectoryItems

Get all project items that may need to be transferred to the
output directory.
============================================================ -->
<Target
Name="GetCopyToOutputDirectoryItems"
Outputs="@(AllItemsFullPathWithTargetPath)"
DependsOnTargets="AssignTargetPaths;_SplitProjectReferencesByFileExistence">

<!-- Get items from this project last so that they will be copied last. -->
<CreateItem
Include="@(ContentWithTargetPath->'%(FullPath)')"
Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
>
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>

<CreateItem
Include="@(_EmbeddedResourceWithTargetPath->'%(FullPath)')"
Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
>
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>

<CreateItem
Include="@(Compile->'%(FullPath)')"
Condition="'%(Compile.CopyToOutputDirectory)'=='Always' or '%(Compile.CopyToOutputDirectory)'=='PreserveNewest'">
<Output TaskParameter="Include" ItemName="_CompileItemsToCopy"/>
</CreateItem>
<AssignTargetPath Files="@(_CompileItemsToCopy)" RootFolder="$(MSBuildProjectDirectory)">
<Output TaskParameter="AssignedFiles" ItemName="_CompileItemsToCopyWithTargetPath" />
</AssignTargetPath>
<CreateItem Include="@(_CompileItemsToCopyWithTargetPath)">
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>

<CreateItem
Include="@(_NoneWithTargetPath->'%(FullPath)')"
Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
>
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>
</Target>

有了这个解决方法,我发现在一个解决方案中拥有多达 > 120 个项目是可行的,这有一个主要好处,即项目的构建顺序仍然可以由 VS 确定,而不是通过拆分手动完成解决方案。

关于c# - "Copy Local"和项目引用的最佳实践是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/280751/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com