C# project, compiler complaining missing reference

2019-07-13 08:54发布

I am using Visual Studio 2017 to build a big C# project (200+ projects in the solution). When compiling one of the projects, I got many errors as shown below:

error CS0012: The type 'BufferingAppenderSkeleton' is defined in an assembly that is not referenced. You must add a reference to assembly 'log4net, Version=1.2.11.0, Culture=neutral, PublicKeyToken=1b44e1d426115821'.

The project in question, however, does reference to log4net 1.2.11. The only thing suspicious is the net40-full found in the package path of log4net: "C:\XXXX\Src\packages\log4net.1.2.11\lib\net40-full\log4net.dll"

in the package.config of the project, it contains this line:

<package id="log4net" version="1.2.11" targetFramework="net461" />

and in its app.config, it contains this line:

      <dependentAssembly>
    <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" culture="neutral"/>
    <bindingRedirect oldVersion="0.0.0.0-1.2.11.0" newVersion="1.2.11.0"/>
  </dependentAssembly>

I wonder if it's the mismatch of the .net version (4.0 vs. 4.61) that causes the compiling error?

C# is not my primary area of expertise, but my understanding is that nuget looks into those config files to download needed packages, in this case, log4net. Then how come did it download the 4.0 version rather than that of 4.6.1?

1条回答
劫难
2楼-- · 2019-07-13 09:31

my understanding is that nuget looks into those config files to download needed packages, in this case, log4net.

NuGet's job is just to download packages and extract whatever's in them, at least in the restore scenario of a package.config project. The targetFramework attribute in the packages.config file is only written, never read by the nuget client. I have no idea what it's purpose or intention was. Anyway, I believe the value of targetFramework is just the .NET Framework your project was using when the package was installed.

Then how come did it download the 4.0 version rather than that of 4.6.1?

Background information, skip to the next paragraph if you really don't care. If you go to the package page on nuget.org, you'll see in the version history that 1.2.11 isn't shown. However, if you look at the URLs for other versions, you can guess the URL for version 1.2.11. Quick off-topic comment, Fabio M was close, but not quite correct in saying the package doesn't exist any more. "nuget.org does not support permanent deletion of packages. Doing so would break every project depending on the availability of the package, especially with build workflows that involve package restore.". On the package version page, there's a message saying "The owner has unlisted this package. This could mean that the package is deprecated or shouldn't be used anymore".

Back to my point, once you're at this URL, change the n to an f in nuget.org to see the package version on fuget.org. Next to frameworks you can see a list of frameworks the package supports. net40 is the highest version that the package supports.

So, the reason why NuGet "downloaded the 4.0 version" is because that's the closest version that the nuget package provides that is compatible with your project. .NET is generally considered to be forward compatible, so net45 binaries work on the net462 runtime, so it's generally ok to use net45 binaries when your project is using a newer version.

Finally, about the error you're getting, as I said in my first paragraph, in packages.config projects, nuget's job is just to download and extract the package. At install time it adds some information to the csproj so the compiler can try to find the dll. So, if you look at your csproj, you should find a reference to log4net.dll, and it will contain a hint path that the compiler uses. If that hint path is wrong, then you'll get the errors you see. This is most common when projects are moved in the directory structure, but don't re-install the package. For example if the repo structure was origignally "project\project.csproj" and it's changed to "src\project\project.csproj", then the hint path of "..\packages\log4net.1.2.11\lib\net45\log4net.dll" is wrong, because an additional "..\" needs to be added so the relative path to the packages folder is correct. There may be other reasons the hint path is wrong, but this is the most common reason.

查看更多
登录 后发表回答