.NET 8中NuGet依赖未复制到目标目录问题(对比.NET 4.7.2)
我有一个支持插件扩展的项目,插件通过MEF加载,因此可执行程序(Executable)与插件(Plugin)之间无直接依赖关系。
项目依赖关系:Executable与Plugin无直接依赖,两者均依赖Contracts项目。
完整重建解决方案时,目标框架为net472的构建会将所有必要依赖(包括Enums.NET.dll)复制到目标目录,程序可正常运行;但目标框架为net80的构建不会复制这些依赖,导致运行时找不到Enums.NET.dll。
net80目标目录仅包含Executable、Plugin及Contracts的程序集,缺少Enums.NET.dll等第三方依赖;而net472目标目录包含所有必要的第三方依赖DLL,两者内容差异明显。
核心问题:如何强制net80构建时将所有必要DLL复制到目标目录?
注:该问题并非Enums.NET独有,使用Microsoft.EntityFrameworkCore等包时也会出现相同情况。
上下文代码
Executable项目的CSPROJ文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFrameworks>net472;net80</TargetFrameworks> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <LangVersion>latest</LangVersion> <OutputPath>$(SolutionDir)bin\$(Configuration)</OutputPath> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\Contracts\Contracts.csproj" /> </ItemGroup> <ItemGroup> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.*" /> <PackageReference Include="System.ComponentModel.Composition" Version="8.*" /> </ItemGroup> </Project>
Plugin项目的CSPROJ文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net472;net80</TargetFrameworks> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <LangVersion>latest</LangVersion> <OutputPath>$(SolutionDir)bin\$(Configuration)</OutputPath> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\Contracts\Contracts.csproj" /> </ItemGroup> <ItemGroup> <PackageReference Include="Enums.Net" Version="5.*" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.*" /> <PackageReference Include="System.ComponentModel.Composition" Version="8.*" /> </ItemGroup> </Project>
解决方案资源管理器结构:包含Executable、Plugin、Contracts三个项目。
针对.NET 8的依赖复制问题,可采用以下几种有效方案:
方案一:启用CopyLocalLockFileAssemblies
在Executable项目的<PropertyGroup>中添加以下配置,强制将所有锁定文件(lock file)中的依赖复制到输出目录:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
该配置会让.NET构建系统将项目依赖图中的所有间接依赖都复制到输出目录,适用于需要统一管理所有依赖的场景。
方案二:添加无编译依赖的项目引用
在Executable项目中添加对Plugin项目的引用,但通过PrivateAssets="All"排除编译时依赖,仅保留构建时的依赖复制逻辑:
<ItemGroup> <ProjectReference Include="..\Plugin\Plugin.csproj" PrivateAssets="All" /> </ItemGroup>
此方式既保持了Executable与Plugin的无编译依赖关系,又能让构建系统自动复制Plugin的所有依赖到共同输出目录。
方案三:显式复制插件依赖
在Plugin项目中添加<CopyToOutputDirectory>配置,将第三方依赖显式复制到输出目录:
<ItemGroup> <PackageReference Include="Enums.Net" Version="5.*"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </PackageReference> </ItemGroup>
此方案适合仅需复制特定依赖的场景,但需要逐个配置第三方包,维护成本较高。
内容的提问来源于stack exchange,提问作者Sebastian Schumann

