Assembly.ReflectionOnlyLoad Ignores Assembly Binding Redirects
This is a short post to make you aware of the fact that Assembly.ReflectionOnlyLoad does not honor assembly binding redirects.
Assembly binding redirection allows you to specify at the machine- or application-level that if an application attempts to load a certain version of an assembly, it should load another version instead. For example, I don’t have .NET 1.0 installed on my system, but .NET 1.0 applications can run successfully because there are binding redirects in place. For example, when an application requests the 1.0.3300.0 System.Data.dll assembly, a binding redirect will give it the 4.0.0.0 version.
This is what a Fusion log for this redirect looks like (edited for brevity):
=== Pre-bind state information ===
LOG: DisplayName = System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
(Fully-specified)
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Version redirect found in framework config: 1.0.3300.0 redirected to 4.0.0.0.
LOG: Post-policy reference: System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
LOG: Reusing an assembly instance that was previously loaded (C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll).
On the other hand, Assembly.ReflectionOnlyLoad disregards binding redirects and loads only the specific assembly version that you requested. Therefore, trying to load the 1.0.3300.0 System.Data.dll using a reflection-only load produces this Fusion log and an exception:
=== Pre-bind state information ===
LOG: DisplayName = System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
(Fully-specified)
===
LOG: This is an inspection only bind.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: GAC Lookup was unsuccessful.
…
LOG: All probing URLs attempted and failed.
By the way, after trying the GAC, the loader actually tries to look for the assembly in the AppDomain’s base directory and probing path. This can lead to pretty surprising exception messages. Hopefully, this bug won’t bite you now that you know this is by design.
[By the way, this bug affected me because I had some code loading assemblies for reflection-only and pre-loading their references (references are not loaded automatically for reflection-only assemblies). This pre-loading would fail if there ever were a reference that required an assembly binding redirect to resolve…]