I am splitting many of my application models and interfaces into its own nuGet package.
The question is: Is there any good practice recommended strategy when creating nuGet packages regarding the definition of dependencies?
Sometimes a package A
depends on a package B
. If I don't declare a specific package B
version on my package A
's nuspec, when I later on import package A
nuGet package in any solution, it may fail at runtime because the the subdependency was not available.
Sometimes the dependency tree goes even deeper. But If I explicitly add dependencies onto each nuspec file, then I could find version conflicts later on.
The question is: What's the recommended strategy to deal with these things if everything is under my control? Should I only specify dependencies when the dependency is something "not obvious" for the project (e.g: a third party library that the project importing a nuGet wrapper needs at runtime but doesn't use directly)? Should I do it always and later on deal with version conflicts in a different way? Any good source of information regarding this would be much appreciated as I found several examples but not a recommendation of a certain way to do things.
ANNEXED: The way I create nuGet packages is by including a nuspec file which I edit manually. For example if I have the following solution structure:
ToolBelt.CityContracts.sln
-ToolBelt.CityContracts.NuGet
--ToolBelt.CityContracts.NuGet.nuspec
-ToolBelt.CityContractsOne
-ToolBelt.CityContractsTwo
In ToolBelt.CityContractsOne
and ToolBelt.CityContractsTwo
I have my c# source files. And From ToolBelt.CityContracts.NuGet
project I add a reference to ToolBelt.CityContractsOne
and ToolBelt.CityContractsTwo
to make sure that the nuspec "knows" where the source files are.
Then the nuspec looks something like this:
<?xml version="1.0" encoding="utf-8" ?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>ToolBelt.CityContracts</id>
<version>1.0.0</version>
<authors>iberodev</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Shared Contracts</description>
<dependencies>
<!--here sub-dependencies that I want to drag across-->
</dependencies>
</metadata>
<files>
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsOne.dll" target="lib/netstandard2.0" />
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsOne.pdb" target="lib/netstandard2.0" />
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsTwo.dll" target="lib/netstandard2.0" />
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsTwo.pdb" target="lib/netstandard2.0" />
</files>
</package>
Everything pretty standard until here.
Then I use nuget command tool to generate the nuget package inside a folder called nupkgs
with the command:
nuget pack ToolBelt.CityContracts.NuGet.nuspec -Version $VERSION -OutputDirectory nupkgs -Prop Configuration=Release -NoDefaultExcludes -Verbosity detailed
UPDATE 1: For now my strategy is the following.
- If the
package A
exposes classes/interfaces in its public API that are part of apackage B
, then thepackage A
does not add a dependency topackage B
in its nuspec. Therefore the project that addspackage A
must also explicitly addpackage B
- If the
package A
does not expose classes/interfaces in its public API that are part of apackage B
but it uses them internally, then thepackage A
must add a dependency topackage B
in its nuspec, so that the project that addspackage A
will also havepackage B
installed automatically and avoid the runtime exception risk.
The idea is: if the code compiles, it should run without runtime exceptions due to inexisting dependencies.
This makes sense to me, but I cannot find any reliable source to confirm that this is the way to go.