TPic
TPic

Reputation: 51

How can I mark dependencies for runtime only in a .nuspec file?

I am using Visual Studio 2017, with the old style .csproj file format.

I am trying to build up a set of NuGet packages.

The initial layer (C NuGet package) exposes some piece of core functionality.The middle layer (B NuGet package) pulls in C and provides a set of methods. So, B has a dependency on C. The .nuspec for B lists C as a dependency.

Finally, I have an application (A Application) that pulls in the B NuGet package. What I am trying to avoid is my application having references to C, but since C is marked as a dependency in B it gets added.

I do not want Visual Studio to add in a reference to C for application A. I just need C artifacts at runtime so that B still works correctly.

A <-- B <-- C

If the C NuGet package has a foo() method, and I install B NuGet package into application A, application A can use the C.foo() method. I only want application A to use exposed B methods.

How can I create the B .nuspec file to add the C NuGet dependency, but limit its usage to only the B NuGet package? Is there some change I need to make to the C .nuspec file as well?

I have looked into include and exclude flags relating to dependencies, and could not find the combination to achieve what I want.

I tried using the newer .csproj format to let Visual Studio create the NuGet packages for me, but could not get that to work as I want.

If I remove the unwanted C references from application A, I lose those artifacts at runtime, so that did not work.

I see the DevelopmentDependency flag which indicates a package should be excluded from the output. I am kind of looking for the notion of a RuntimeDependency, that is only included in the output.

PrivateAssets / SuppressParent does not sound right, since packages "should be consumed, but not flow to the next project".

Upvotes: 3

Views: 1125

Answers (2)

TPic
TPic

Reputation: 51

I took a much different approach to handle this issue. I am not sure I totally like it, but it serves my needs pretty well.

So, nothing changes with NuGet package C. It gets built and packaged as before.

The goal of NuGet package B was to help facilitate using the logic in C in a service. So, I turned B into a full blown service implementation that still references C. The B NuGet package now consists of one DLL (which contains the service contract interface) that gets pulled into Application A, and uses an Install.ps1 to copy the necessary files into a separate directory. There are no dependencies listed in NuGet B package. So, the only reference in Application A, is that single DLL.

The good is that with everything in separate directories there will be no versioning issues between what B needs and what A needs. Also, A does not get burdened with unnecessary dependencies from B. It isn't the greatest, because some DLLs could be shared between the two.

Upvotes: 2

LoLance
LoLance

Reputation: 28116

Finally, I have an application (A Application) that pulls in the B NuGet package. What I am trying to avoid is my application having references to C, but since C is marked as a dependency in B it gets added.

It's expected behavior I think. If we have two nuget packages, A depend B with <dependency id="B" version="xxx" /> in .nuspec file, the application which consumes Package B will automatically install and reference Package C. And this point can be obviously proved when you use packages.config format to manage nuget packages.

So it's hard to get what you want in this way.

How can I create the B .nuspec file to add the C NuGet dependency, but limit its usage to only the B NuGet package?

When your Package B depend on Package C, if you consume Package B, it will reference Package C as well. So there's possibility to do what you want if the Package C is only used to provide C.dll as content during runtime. (It means if we reference Package C directly, it won't reference C.dll directly, only in this way it's possible for what you expected)

But if it's what you want. Why not contain the C.dll into B.nupkg. We only need to create B package which contains C.dll(not in lib folder when packing), then when we Consume B package in A, it will only reference B.dll. It works well during build time. And for the runtime, we just need to copy the C.dll into output folder. Then it works in both build time and runtime.

See Content files element in .nuspec or including targets in nuget, either of these two ways may help resolve your issuebut since I not familiar with Content files, so I use custom msbuild target to do this, and it works. Feel free to let me know if I misunderstand anything or there's better way :)

Upvotes: 0

Related Questions