My scenario is that I have a Code Generation tool that uses certain class library assemblies as input. In the past, I had a local "packages" directory that NuGet would copy referenced packages to, and I could use those to find the assemblies and run the code generator using them as input (or I could look in the output directory of my class library, since building a .Net Framework class library would copy all of the assembly files it referenced to the output directory).
Now, switching over to the new .csproj and .Net Standard from only developing for the .Net Framework, NuGet puts the packages somewhere else on the machine whose location is pretty opaque, and the build of a class library no longer copes the assembly files of dependencies to the class library's output folder.
Basic structure: SharedClassLibraryA
- Package stored in internal NuGet source
- Targets netstandard2.0
SharedClassLibraryB
- Package stored in internal NuGet source
- Depends on A
- Targets netstandard2.0
SharedClassLibraryC
- Part of my solution
- Has a PackageReference to SharedClassLibraryA and SharedClassLibraryB
- Targets netstandard2.0;net47
TestProject
- Part of my solution
- Has a PackageReference to SharedClassLibraryA and SharedClassLibraryB
- Has a ProjectReference to SharedClassLibraryC
- Targets netstandard2.0;net47
- The code generator runs before building this and takes assembly files as command line options in order to use reflection and generate code. EDIT: This generated code is then compiled in the compile step.
The problem that I am encountering is that building a non-.Net Framework target doesn't copy the assembly files that the dependencies rely on to the output folder, so I can't point to SharedClassLibraryC's output folder to find the SharedClassLibraryA and the SharedClassLibraryB assembly files for my code generator to take as input.
Also, the NuGet packages aren't expanded into a folder that is local to my code, so I can't grovel through there to get the assembly files, either. (And that required knowing the version number and other details of the package's folder structure.)
Building the .Net Framework target does copy the assembly files for SharedClassLibraryA and SharedClassLibraryB to the output directory of SharedClassLibraryC, so that works for that target. (I would like to take out the .Net Framework target at some point, though.)
I have tried adding a BeforeTargets="BeforeBuild" Target to the TestProject that runs dotnet publish on SharedClassLibraryC to have it copy all the assembly files of its dependencies to a folder that the code generator can point to; however, you can't tell it not to build the project that you are running dotnet publish against, so a build of the solution builds SharedClassLibraryC 4 times (once each for building SharedClassLibraryC for netstandard2.0 and net47, and once each from dotnet publish running when building TestProject for netstandard2.0 and net47).
EDIT: The solution at https://stackoverflow.com/a/43841481/8748148 copied the NuGet package DLL files to the output directory (bin\Debug\netstandard2.0
, in my case) which solves my immediate problem:
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
I will look into the DependencyContext
API; I suspect that this code generator took assembly file paths on the command-line to narrow down what it had to load and look for its attributes in, but it may be a lot simpler to just look in the whole dependency tree.