Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encapsulating nuget package adds child dependency transitively #7111

Closed
ronnyek opened this issue Jul 12, 2018 · 11 comments
Closed

Encapsulating nuget package adds child dependency transitively #7111

ronnyek opened this issue Jul 12, 2018 · 11 comments
Labels
Functionality:Pack Functionality:Restore Resolution:NotABug This issue appears to not be a bug WaitingForCustomer Applied when a NuGet triage person needs more info from the OP

Comments

@ronnyek
Copy link

ronnyek commented Jul 12, 2018

Details about Problem

I've thought about how to succinctly put my question / problem into words... trying to provide a concrete example

I'm attempting to encapsulate or wrap a library, to control how its accessed. For the purposes of this example lets consider StackExchange.Redis. Ideal workflow, people (my colleagues) would install my wrapper, they'd get my wrappers, and additionally the stackexchange.redis nuget package dll would be copied, but not explicitly referenced directly where my wrapper is consumed.

SomeApp --> CachingWrapper --> StackExchange.Redis
is what I desire... installing my CachingWrapper internally uses StackExchange.Redis, and even adds dll to the compile time stuff, bin folder etc... but doesn't explicitly add reference

What happens today
SomeApp --> CachingWrapper --> StackExchange.Redis
|--------------------------------------------^

References automatically get added to stackexchange.redis directly, and mess with the ide.

As it is now, we install my wrapper, and it automatically adds reference to my library's child dependencies which pollute intellisense etc.

I'm not trying to specifically exclude people from being able to explicitly install stackexchange.redis, but not reference it at development time by default. I've been told I could just create a nuspec where the stackexchange.redis gets added as "content" which probably would work, but remove any ability to automatically handle versioning etc.

I've tried varying configurations of settings in my .csproj for the references to stackexchange.redis with PrivateAssets="compile" but with also the flags for all etc... and it seems like the differences I've seen is just that I can publish my nuget, but forces the end consumer to explicitly add a reference to stackexchange.redis

NuGet product used (NuGet.exe | VS UI | Package Manager Console | dotnet.exe):
dotnet (with pack flags)

NuGet version (x.x.x.xxx):
3.4.3.855

dotnet.exe --version (if appropriate):
2.1.301

VS version (if appropriate):
2018

OS version (i.e. win10 v1607 (14393.321)):
win 10

Detailed repro steps so we can see the same problem

  1. Create class library that references any nuget package

  2. Run dotnet pack somelibrary.csproj

  3. Install somelibrary nuget into another project

  4. Observe child nuget package dependencies automatically get added to your consumer, and namespaces are all accessible to intellisense etc.

...

Other suggested things

I'm not sure if this is a bug, or this is an artifact of how netcore handles typeloading, or if this is purely intentional. This does work if I reproduce the same things as csproj references in pre-netcore and avoid nuget packages.

Also, I'd be more than happy to help contribute changes to packager or installer or whatever is making this not work today.

Appreciate the time folks!

@PatoBeltran
Copy link

PatoBeltran commented Jul 14, 2018

Hey @ronnyek thanks for opening the issue! ExcludeAssets="compile" should be the solution you are looking for. This basically tells the compiler in the package consumer's machine to not compile against your dependency dlls. Is this breaking your scenario? What's happening and what do you expect to happen?

Here is a link to a previous related issue that we had #6614

@PatoBeltran PatoBeltran added Product:NuGet.exe NuGet.exe Functionality:Pack WaitingForCustomer Applied when a NuGet triage person needs more info from the OP labels Jul 14, 2018
@ronnyek
Copy link
Author

ronnyek commented Jul 14, 2018

With it set to compile it will build a package and my consumer can install it... But for my library to work I still have to install the child dependency into the consumer itself directly... Thus being really no better off.

I'm trying to make it so installing my package would bring along the child reference... But child reference wouldn't be automatically added at dev time. I don't want intellisense suggestions for inner library classes and methods... Just my library. (I guess unless they insist on adding a reference to the inner dependency... In which case what are you going to do...)

@ronnyek
Copy link
Author

ronnyek commented Jul 17, 2018

In addition to this, it seems like setting ExcludeAssets="compile" seem to introduce my consuming applications to explicitly require a reference to the inner nuget package... which introduces a world of versioning problems

@ronnyek
Copy link
Author

ronnyek commented Jul 17, 2018

I think there is a learning opportunity here for myself, and I think there is a chance I'm using the wrong tool for the job.

Outside of PrivateAssets / IncludeAssets/ ExcludeAssets, is there a way to make a child nuget dependency something that gets installed when my lib is installed, but not just blindly added as a reference to the consumer of my library.

(Eg, I suspect if I were to manually copy StackExchange.Redis to my project, and build a custom nuget package where StackExchange.Redis was considered a content file that just got copied into the bin folder, my consumer would be able to load my library, which would load StackExchange.Redis, but users wouldnt just automnatically have intellisense polluted)

The problem with the above scenario is that its hacky, and basically lose any value of any version parity (other libs that also require StackExchange.Redis)

@ronnyek
Copy link
Author

ronnyek commented Jul 17, 2018

As perhaps a more simple example... I just installed Microsoft.Extensions.Caching.Redis to a new dotnet core web application... and then in code started typing ConnectionMulti... and visual studio suggested I import StackExchange.Redis which basically removes any ability to encapsulate.

My understanding is this is just the way .net core / nuget work, so other than just maybe having fature request for options for some flexibility, I guess this is what it is

@nkolev92
Copy link
Member

nkolev92 commented Aug 1, 2018

But for my library to work I still have to install the child dependency into the consumer itself directly... Thus being really no better off.
I'm trying to make it so installing my package would bring along the child reference... But child reference wouldn't be automatically added at dev time. I don't want intellisense suggestions for inner library classes and methods... Just my library. (I guess unless they insist on adding a reference to the inner dependency... In which case what are you going to do...)

That's exactly what you can achieve with excludeAssets="Compile" at the caching wrapper.
It'll be there during runtime, but not in the intelisense.

In addition to this, it seems like setting ExcludeAssets="compile" seem to introduce my consuming applications to explicitly require a reference to the inner nuget package... which introduces a world of versioning problems

They don't require a reference to the inner nuget package. Why would they? It'll already be brought in transitively.

Please refer to https://github.com/nkolev92/NuGet.Tools/tree/50a517e69f812e5b328102a56127fc3d24221e7e/LimitingTransitiveAPIflow where I have some POCs on limiting API flow.

It'd be great if you can provide a repro of what you're actually doing so we can try it out on our end.

@ronnyek
Copy link
Author

ronnyek commented Aug 2, 2018

Sounds good. I'll try this out... If nothing else, I'll provide a reproduction project.

@ronnyek
Copy link
Author

ronnyek commented Aug 2, 2018

Comparing to: https://github.com/nkolev92/NuGet.Tools/blob/50a517e69f812e5b328102a56127fc3d24221e7e/LimitingTransitiveAPIflow/LeafLibrary/ConsumerWithSupressedTransitiveAPI/ConsumerWithSupressedTransitiveAPI.csproj

Is this like saying applications that consume my caching wrapper would have to explicitly go set PrivateAssets="all" ExcludeAssets="compile" in the csproj file?

When I set those inside of my library project that consumes stackexchange.redis, the library itself complains about not being able to reference stackexchange.redis.

If the intention is that one would have to manually add that after installing my library package, that kinda seems like it would work, but because it requires manual intervention, may be of little value.

@nkolev92
Copy link
Member

nkolev92 commented Aug 2, 2018

Shouldn't be necessary.

That specific ask there was how to limit intellisense pollution for transitive libraries and the only way to get that to work is to bring it up top level.
I have created an issue for that specific ask
#6720

Yours is a bit different.

@jainaashish
Copy link
Contributor

@ronnyek you should set developmentDependency to true on your wrapper library so that when your library is installed, it will automatically set PrivateAssets and excludeAssets on the package reference.

More details in https://docs.microsoft.com/en-us/nuget/reference/nuspec

@jainaashish jainaashish added the Resolution:NotABug This issue appears to not be a bug label Aug 30, 2018
@royben
Copy link

royben commented May 20, 2021

@ronnyek
This is exatcly what I'm looking for.
Did you manage to resolve that issue ?

@nkolev92
Are there any news about this ?
Is it possible to encapsulate only the intellisense of a referenced package?

Thanks,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Functionality:Pack Functionality:Restore Resolution:NotABug This issue appears to not be a bug WaitingForCustomer Applied when a NuGet triage person needs more info from the OP
Projects
None yet
Development

No branches or pull requests

5 participants