dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.71k stars 1.07k forks source link

Reference to assembly on disk does not resolve assembly nuget package dependencies properly #1425

Closed davidxu19 closed 7 years ago

davidxu19 commented 7 years ago

@eerhardt This issue is related to https://github.com/dotnet/sdk/issues/120.

This happened in VS 2017 15.3 Preview 4.0. .net Core SDK version is 2.0.0-preview2-006497.

Here is the project structure and how to reproduce the issue.

  1. netStandardLibTest1 is a class library targeting .netstandard2.0. It has a reference to System.IO.Packaging Nuget package.
  2. netCoreTest1 is a console app that references netStandardLibTest1 as a dll.
  3. When debugging or running netCoreTest1, it failed with FileNotFoundException for System.IO.Packaging. Also netStandardLibTest1 referenced 4.4.0 preview2 version of System.IO.Packaging, and the error mentioned version 4.0.2.0 somehow.

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.IO.Packaging, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03 f5f7f11d50a3a'. The system cannot find the file specified. at netCoreTest1.Program.Main(String[] args)

  1. If I change assembly reference to project reference, it works properly.

projects

Based on https://github.com/dotnet/sdk/issues/120, assembly reference issue has been fixed in .net Core 2.0 SDK.

I did notice that, if I remove Nuget package reference in netStandardLibTest1 library, the assembly can be loaded properly. So it seems that assembly reference itself has been fixed in SDK Preview 2, but it cannot resolve the assembly's nuget package dependencies properly.

I have attached a zip of my sample projects. Dev.zip

Here is the project execution and assembly loading output with COREHOST_TRACE=1. Assembly reference loading issue.txt

Is there any workaround for this issue? Adding netStandardLibTest1.deps.json under netCoreTest1 bin folder did not help. I also tried to add a nuget.config file into netCoreTest1 project, and specify my local nuget package directory, and it did not help either.

My company has a large .net based project that we want to migrate to .net core. It includes 100+ C# assemblies, and many of them are common libraries. Not being able to reference dlls directly blocks us from testing our code migration effort properly. Any help is appreciated!

eerhardt commented 7 years ago

Sorry for the delay. I was on leave from work, but I'm back now.

The SDK doesn't have the ability to take a referenced .dll and get the transitive closure of its dependencies. When you reference an assembly on disk, like

    <Reference Include="netStandardLibTest1">
      <HintPath>..\netStandardLibTest1\bin\Debug\netstandard2.0\netStandardLibTest1.dll</HintPath>
    </Reference>

your project only references that assembly. Not any other assemblies it references as well.

The supported scenarios are to either:

  1. Use a ProjectReference in netCoreTest1.csproj to netStandardLibTest1.csproj.
  2. dotnet pack the netStandardLibTest1.csproj into a nuget package, and PackageReference it from netCoreTest1 .
  3. Manually add the references in netCoreTest1.csproj to all the assemblies that netStandardLibTest1 requires. ex. Adding <PackageReference Include="System.IO.Packaging" Version="4.4.0-preview2-25405-01" /> to netCoreTest1.csproj fixes the issue in Dev.zip.

/cc @nguerrera @dsplaisted @davkean

Unless someone disagrees, I will close this issue since this scenario isn't supported.

davkean commented 7 years ago

@davidxu19 Assemblies themselves don't carry enough information for us to figure out that they depend on a NuGet package. If we did copy the packages binaries with the assembly at the time you built netstandardlibtest1 project (similar to what we do with other raw binaries that the project references) - they wouldn't be the right ones for the consumption in netcoretest1.

You could generalize @eerhardt's 1) solution where you carry a "MSBUild targets" file with each raw reference that simply contains a <PackageReference/> for its dependencies that you also import where you add the ref - but in the end this is sounding very much like a NuGet package, so you may as well do 2 - especially given we do all the hard work in creating the package.

nguerrera commented 7 years ago

I agree with closing this by design. Thanks, guys for the detailed answers on how to achieve the scenario via supported means.

moh-hassan commented 7 years ago

The same issue happen in vs2017.3 RTM, netcore 2.0 (final release). see #5955 Please, reopen this issue, because with the final release of .NET Core 2.0, this scenario is supposed to be supported. Quote from the article:

You can now reference .NET Framework libraries from .NET Standard libraries using Visual Studio 2017 15.3. This feature helps you migrate .NET Framework code to .NET Standard or .NET Core over time (start with binaries and then move to source). It is also useful in the case that the source code is no longer accessible or is lost for a .NET Framework library, enabling it to be still be used in new scenarios.

70% of nuget packages are net45 (full feature) and netstandard1.3 (less feature), and referencing net* dll is necessary until most packages will be netstandard2 ready. Compiler and Unit test are enough to discover any incompatibility issues in these packages, especially the final release of netstandard2 (netcore2) cover all net461 (except 41 class).

dsplaisted commented 7 years ago

Hi @moh-hassan, it looks like the issue you're hitting is different than the one here, so instead of re-opening this issue, I've moved the original issue you filed in the NuGet repo to #1621.

Thanks!