Location>code7788 >text

How to convert project references to package dependencies when packaging C# Multi-projects

Popularity:18 ℃/2025-04-10 23:30:18

Project background

A group of class libraries has been developed recently, and there will be about five or six projects. A Core, plus several implementation libraries for different products, A/B/C/D... they all rely on Core.

First of all, I want to unify the version number, this is easy to set by.

Secondly, each library must be packaged separately.

The problem is that in the development stage, sub-projects refer to Core through project, which is easy to debug. How to automatically add dependencies on Core packages when packaging?

After experiments, three methods can be summarized:

1. Convert ProjectReference to NuGet dependencies during generation (Not Work)

This DeepSeek recommended solution, but unfortunately, I did not succeed in experimenting.

Its project structure is as follows:

<ItemGroup>
  <ProjectReference Include="..\Core\" >
    <PrivateAssets>all</PrivateAssets>
    <Publish>true</Publish>
    <Version>$(PackageVersion)</Version>
    <PackageId></PackageId>
  </ProjectReference>
</ItemGroup>


<Target Name="ForcePackageReferenceConversion" BeforeTargets="GenerateNuspec">
  <ItemGroup>
    <_PackageReferencesToAdd Include="@(ProjectReference->WithMetadataValue('Publish', 'true'))">
      <PackageId>%(PackageId)</PackageId>
      <Version>%(Version)</Version>
    </_PackageReferencesToAdd>
    <PackageReference Include="@(_PackageReferencesToAdd->'%(PackageId)')" Version="%(Version)" />
  </ItemGroup>
</Target>

Its core idea is to cast the project reference in the package reference before generating .nuspec.

I also asked Github Copilot, and it also said ok, but... please give me some advice from experienced gardeners.

2. Quote according to conditions

Project structure:

<ItemGroup>
   <!-- Use ProjectReference during development -->
   <ProjectReference Include="..\Core\"
                     Condition="'$(IsPackaging)' != 'true'" />

   <!-- Use PackageReference when packaging -->
   <PackageReference Include=""
                     Version="$(PackageVersion)"
                     Condition="'$(IsPackaging)' == 'true'" />
 </ItemGroup>

Then use the command to generate:

dotnet pack -p:IsPackaging=true

This method is feasible.

3. Specify the .nuspec file

Finally, I thought of using traditional .nuspec files. (I like the previous package management method, /nuspec, and I don't understand why MS has to stuff everything into the project file.)

Project structure:

<!-- Specify the custom nuspec file path -->
     <NuspecFile></NuspecFile>
     <!-- Pass the MSBuild property to the variable in nuspec -->
     <NaspecProperties>$(NaspecProperties);
       id=$(PackageId);
       version=$(Version);
       company=$(Company);
       authors=$(Authors);
       product=$(Product);
       copyright=$(Copyright);
       license=$(PackageLicenseExpression);
       projectUrl=$(PackageProjectUrl);
       repositoryUrl=$(RepositoryUrl);
       repositoryType=$(RepositoryType);
       icon=$(PackageIcon);
       config=$(Configuration)
     </NuspecProperties>

It assigns the properties defined in it to nuspec one by one.

Verification is feasible.