3

The question originates from the usage of the NuGet package Microsoft.CodeAnalysis 2.0.0 in a .NET Framework 4.6.2 project.

The Microsoft.CodeAnalysis.dll has a reference to: System.Threading.Tasks, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

However, this assembly is nowhere to be found.

The System.Threading.Tasks NuGet package contains no assemblies for .NET 4.6.2 and the GAC contains only version 4.0.0.0 of this assembly (which in turn contains only type forwarders).

But despite this everything works as it should during runtime, and indeed the assembly actually loaded is System.Threading.Tasks, Version=4.0.0.0.

The app.config of my project contains no binding redirects for this assembly either. So how does the CLR resolve it to version 4.0.0.0 of System.Threading.Tasks?

The problem occurs when attempting to load assemblies in the Reflection-Only context, where we have to provide the assembly resolve handler ourselves, since the requested assembly is nowhere to be found and there are no binding redirects or anything hinting that we should actually load a lower version than the requested assembly.

Update

It was suggested that this was a retargetable assembly. Looking at the post here, it suggests that the metadata should contain something like the following:

.assembly extern retargetable mscorlib
{
...
}

But when I look at Microsoft.CodeAnalysis.dll in ILdasm I cannot find any mention of something being retargetable in it. The reference looks like this:

.assembly extern System.Threading.Tasks
{
  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )                         // .?_....:
  .ver 4:0:10:0
}

Could it be that ILdasm is hiding something here?

If I try the following:

Assembly codeAnalysisAssembly = 
Assembly.ReflectionOnlyLoadFrom("Microsoft.CodeAnalysis.dll");
foreach (var reference in codeAnalysisAssembly.GetReferencedAssemblies())
{
   Console.WriteLine(reference.FullName);
}

None of the assembly names returned contains any information that it references a "retargetable" assembly (that I can find).

However the runtime resolves the assembly here does not seem to work in the Reflection-only context though:

// This call succeeds and prints: System.Threading.Tasks, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Console.WriteLine(Assembly.Load("System.Threading.Tasks, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a").FullName);

// This call throws an exception saying it cannot find the requested assembly.
Console.WriteLine(Assembly.ReflectionOnlyLoad("System.Threading.Tasks, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a").FullName);

If fact, it seems that Assembly.Load() will happily load the 4.0.0.0 version of the System assembly as well, no matter which version we request as long as the major.minor part of the version is equal to 4.0. Is there some publisher policy in effect here maybe?

Concrete Questions

  1. What mechanism is the CLR using to "ignore" the versions of the requested System-assemblies when using Assembly.Load?
  2. Is it possible to implement a handler for AppDomain.ReflectionOnlyAssemblyResolve that would mimic this behavior when using Assembly.ReflectionOnlyLoad()? At least without resorting to the native Fusion-API? And if so, how should this be done?
Community
  • 1
  • 1
DeCaf
  • 6,026
  • 1
  • 29
  • 51
  • It is a *retargetable* assembly. Pretty messy detail, [this Q+A](http://stackoverflow.com/questions/11408792/how-does-the-c-sharp-compiler-decide-to-emit-retargetable-assembly-references) talks about it. Not otherwise fundamentally different from the way CLR v4.0.30319 can load an assembly that was built targeting v2.0.50727 and thus has a dependency on, say, v2.0.0.0 of mscorlib.dll, switcheroo at runtime. – Hans Passant Apr 12 '17 at 12:38
  • @HansPassant That explains ...well, half of it anyway. How would I go about manually resolving the correct assembly in the case of the reflection-only context? Is there any information in the *retargetable* assembly saying for which version it is retargettable or something like that? – DeCaf Apr 12 '17 at 13:19
  • You only asked half a question and did not show us what problem you tried to solve. Waste of time to you and us, no real point to that. Probably a duplicate of [this one](http://stackoverflow.com/a/19636730/17034). – Hans Passant Apr 12 '17 at 13:33
  • @HansPassant You are probably right that the question wasn't very clear. Sorry about this. I had no intetion for my comment above to be any form of complaint. I always appreciate your insights! I have updated the question and tried to make it a bit more concrete. (Hopefully I didn't just make it more obscure) – DeCaf Apr 12 '17 at 15:33

0 Answers0