我有一个项目,它创建一个 DLL,并在发布版本中创建一个 Nuget 包。
此包用于没有直接从 EXE 引用的插件中。该插件是动态加载的。
插件和 EXE 都位于解决方案中,并构建在同一目标目录中。
如果只有插件有对Nuget包的引用,则不会将对应的DLL复制到目标目录。一旦 EXE 本身收到对 Nuget 包的引用,依赖项就会被干净地复制到目标目录。
如何强制插件将依赖项复制到目标目录?
如果存在从 EXE 到所用包的直接引用或传递引用,则 dll 将被复制到目标目录。
Nuget包的CSPROJ:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net80-windows</TargetFramework>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
<Product>PkgA</Product>
<LangVersion>latest</LangVersion>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>$(SolutionDir)bin\$(Configuration)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>$(SolutionDir)bin\$(Configuration)</OutputPath>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
<ItemGroup Label="NuGetFileToCopy">
<Content Include=".build\**" PackagePath="build\" />
<Content Include=".build\**" PackagePath="buildTransitive\" />
<Content Include="$(SolutionDir)\bin\$(Configuration)\net80-windows\$(Product).pdb" PackagePath="contentFiles\any\net8.0-windows7.0" PackageCopyToOutput="false" Visible="false" />
<Content Include="$(SolutionDir)\bin\$(Configuration)\net80-windows\$(Product).xml" PackagePath="contentFiles\any\net8.0-windows7.0" PackageCopyToOutput="false" Visible="false" />
</ItemGroup>
</Project>
使用插件的CSPROJ:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net80-windows</TargetFramework>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>$(SolutionDir)bin\$(Configuration)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>$(SolutionDir)bin\$(Configuration)</OutputPath>
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PkgA" Version="0.*" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.*" />
<PackageReference Include="System.ComponentModel.Composition" Version="8.*" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Contracts\Contracts.csproj" />
</ItemGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
</Project>
Nuget 包还有一个
targets
文件,它将 PDB 和 XML 复制到目标目录。这些文件已正确复制到目标目录。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- copy the files to the output directory -->
<ItemGroup>
<_PkgANet80Files Include="$(MSBuildThisFileDirectory)..\..\contentFiles\any\net8.0-windows7.0\*.*" />
<!-- include everything -->
<Content Include="@(_PkgANet80Files)">
<Link>%(Filename)%(Extension)</Link>
<Visible>False</Visible>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Pack>False</Pack>
</Content>
</ItemGroup>
</Project>
创建的
nuspec
-文件是:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>PkgA</id>
<version>0.0.1.7</version>
<authors>PkgA</authors>
<description>Package Description</description>
<repository type="git" commit="ad93ea6a6fa7ededfff35ea75fff94123661a768" />
<dependencies>
<group targetFramework="net8.0-windows7.0" />
</dependencies>
<frameworkReferences>
<group targetFramework="net8.0-windows7.0">
<frameworkReference name="Microsoft.WindowsDesktop.App.WindowsForms" />
</group>
</frameworkReferences>
<contentFiles>
<files include="any/net8.0-windows7.0/PkgA.pdb" buildAction="Content" copyToOutput="false" />
<files include="any/net8.0-windows7.0/PkgA.xml" buildAction="Content" copyToOutput="false" />
</contentFiles>
</metadata>
</package>
原始 NuGet 包将包含本地项目 dll,如果您使用packages.config,则任何 nuget 包都将被列为依赖项。大家都很开心。
微软已经简化了一切,所以现在.Net(核心)一切都是从项目文件完成的,我更喜欢这一点。但现在使用 nuget pack,您生成的包将不会列出任何依赖项。
Microsoft 表示 NuGet 不支持 PackageReferences
NuGet CLI
所以你需要使用 dotnet pack 或 msbuild -t:pack
dotnet CLI
但是现在使用 dotnet pack,您可以为 PackageReferences 恢复依赖项,但您的 ProjectReferences 现在也被列为依赖项.....
下面是一个示例项目文件,其中包含 PackageReferences 和 ProjectReferences。对于项目,它们已被标记为 PrivateAssets="All",然后使用自定义构建目标将项目所需的文件复制到包中。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Title>Some.Project</Title>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Something" Version="1.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Some.Other.Project.csproj" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput> $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<_ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))"/>
</ItemGroup>
<ItemGroup>
<BuildOutputInPackage Include="@(_ReferenceCopyLocalPaths)" TargetPath="%(_ReferenceCopyLocalPaths.DestinationSubDirectory)"/>
</ItemGroup>
</Target>
</Project>
使用 PackageReference 时,NuGet pack 任务不包含依赖项 #10301 当使用 PackageReference 而不是 packages.config 时,nuget pack 忽略依赖项 #5979
约瑟夫·奥托森 (Josef Ottosson) 提供的出色指南和示例,包括参考项目 - 约瑟夫·奥托森 (Josef Ottosson)