@KshitizGIT commented on Sun Sep 03 2017
I have a project layout like this.
Assembly A -> Assembly B -> Assembly C.
Program lives in Assembly A.
ClassB lives in Assembly B.
ClassC lives in Assembly C.
I don't want AssemblyC to be directly accessible in AssemblyA. So I added PrivateAssets = "All" in the ProjectReference element in the AssemblyB.csproj file
ClassB creates a instance of ClassC.
Program creates a instance of ClassB.
But this is causing a System.IO.FileNotFoundException : Couldnot load file or assembly 'C'.
I have attached the project. Please look into it.
This is a scenario that is currently not possible. I have marked it for 2.1.0.
Oh man, I'll be so pleased to see this make it in. I tend to build abstractions so like Blah.Caching, that would maybe internally call redis client, or something. I dont mind having a phsyical reference to redisclient dlls, or automatically importing nugets, but the redisclient namespaces being automatically accessible defeats the purposes of building abstractions for my developers.
Thanks again!
Not available? Damn! I don't want any part of my solution to have access to App.DataAccess.EntityFramework except my App.Bootstrapper project, but as soon as my app references App.Bootstrapper it has access to lots of stuff I don't want other developers instantiating. Setting PrivateAssets="All" seemed to be the solution I needed, but now the app doesn't even run!
@livarcocc I was just looking through the 2.1.0 milestone (https://github.com/dotnet/corefx/milestone/12),but I don't see this issue in the list (event though I see in the history above that it was added on October 9). Hovering over the 2.1.0 text, it says the milestone has been deleted.
Is this still slated for 2.1.0 and just needs to be migrated into the (apparent) new 2.1.0 milestone, or is it getting pushed back?
No judgement. Just curious. 馃榿
I am not sure about the corefx milestones, but this issue is already marked for 2.2.0 of the SDK, which currently, will carry the 2.1.0 of the runtime.
Whoops!
I completely didn't realize I had wound up in the corefx
repo!
Sorry about that, I definitely see it in the 2.2.0 milestone, as you said.
Thanks!
I'm not sure I get the feature here - isn't this how PrivateAssets is supposed to work?
If I create a NuGet package referencing another with PrivateAssets="All"
then I only use resources during build time - useful for build logic only packages or static analysis annotation libraries like JetBrains.Annotations. If I want to use another library at runtime, I cannot use PrivateAssets="All"
.
I guess the NuGet equivalent would be Exclude="Compile"
but I don't know if this has any support on ProjectReference
I might be misunderstanding, myself, but if we look at full-fat .NET Framework...
If I have a console app that references ProjectA and ProjectA references ProjectB, when I start coding within the console app, as long as A doesn't expose publicly any of the types from B,I don't get autocomplete choices from B and I'm not required to add a reference to B in the console app.
(That might cause runtime errors because of a longstanding issue with MSBuild where if you truly wrap a library to the point where it's not exposed at all, MSBuild won't wind up copying it to the final output path--our console app in this case.)
The "transitive dependencies" in .NET Core/Standard seemed like they might be the solution to this, because they're tracking the dependencies of your dependencies.
The downside is that if I'm trying to hide the implementation details of something, I can no longer do that. The moment I reference my wrapper library all of its dependencies become transitively referenced as well. So consumers of my library are now able to directly access the members of the library that's being wrapped (as well as all of the libraries that one uses. This includes seeing types with no public constructors that they will never be able to instantiate in their own.
It might be that I don't understand the true purpose of the attribute in question, but it seemed to be offering that hint that "you should expose my dependencies to the consumer, except in whatever way is required for me to function" which would, to me, mean "you should obviously copy my dependencies around as part of the build because I need them to run, but don't force them on consumers. If they want them, they can reference them directly."
Far from an expert on the topic, and perhaps there's another way to hide the implementation details. But that's my take on it.
How can this be closed? How can such a serious flaw not be addressed?!?
There must be a clean solution for it or it is not possible to do any clean code development with .NET Core...
At the moment the best way to do this is making internal implementation details internal
to that assembly.
I have heard this ask multiple times now, most of them being "I don't want some dev to accidentally reference XY, especially our juniors are prone to this".. My 2 cents on this is that no technical tool/config can replace proper development processes like code reviews on PRs, CI/CD etc.
The thing that will probably work best in this situation would be a roslyn analyzer that disallows using types of special namespaces. I've never come around to writing one but it should be possible (e.g. write an anylyzer with some sort of configuration to tell it not to allow use of MongoDb
types in API projects etc.).
At the moment it is quite difficult to filter out assemblies being passed to MSBuild / Roslyn and still ending up with a proper dependency graph. There is a lot of black magic going into resolving assembly references, detecting and resolving conflicts etc. so removing some references may end up having worse effect, especially on full framework (msbuild can autogenerate assembly redirects if you tell it to.. but only if it sees all the DLLs).
Is this issue outdated?
I've been doing tests similar to the project the author described (ConsoleApp -> ClassLib1 -> ClassLib2) and normally <ProjectReference>
is transitive so ClassLib2 is available in ConsoleApp when I project reference only ClassLib1.
But When I use <ProjectReference Include="..\ClassLib2\ClassLib2.csproj" PrivateAssets="All" />
in ClassLib1
project then ClassLib2 is not available in ConsoleApp (compiler error).
Similar when I put <DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
(learned bout it here) in ConsoleApp .
But in all cases my application works, ClassLib2 is copied to bin folder of my ConsoleApp, even though the compiler doesn't see it (this is good and what I expect).
So I downloaded the sample project the autor uploaded in 2017 (Dependency.zip) and checked it.
And it also works! No FileNotFoundException. 馃槷馃槕
So was it changed in some release of .Net Core (or.Net Core SDK, I'm using old net48 with new SDK-csproj)?
If so when was it changed and why this issue is still open and have been added to 2.2.1xx milestone?
Most helpful comment
I might be misunderstanding, myself, but if we look at full-fat .NET Framework...
If I have a console app that references ProjectA and ProjectA references ProjectB, when I start coding within the console app, as long as A doesn't expose publicly any of the types from B,I don't get autocomplete choices from B and I'm not required to add a reference to B in the console app.
(That might cause runtime errors because of a longstanding issue with MSBuild where if you truly wrap a library to the point where it's not exposed at all, MSBuild won't wind up copying it to the final output path--our console app in this case.)
The "transitive dependencies" in .NET Core/Standard seemed like they might be the solution to this, because they're tracking the dependencies of your dependencies.
The downside is that if I'm trying to hide the implementation details of something, I can no longer do that. The moment I reference my wrapper library all of its dependencies become transitively referenced as well. So consumers of my library are now able to directly access the members of the library that's being wrapped (as well as all of the libraries that one uses. This includes seeing types with no public constructors that they will never be able to instantiate in their own.
It might be that I don't understand the true purpose of the attribute in question, but it seemed to be offering that hint that "you should expose my dependencies to the consumer, except in whatever way is required for me to function" which would, to me, mean "you should obviously copy my dependencies around as part of the build because I need them to run, but don't force them on consumers. If they want them, they can reference them directly."
Far from an expert on the topic, and perhaps there's another way to hide the implementation details. But that's my take on it.