CLR 4: Making the AssemblyResolve event more useful
In the introductory post on CLR Binder (‘Understanding the Binder – Part 1’), we listed the set of steps that the CLR Binder follows, in order to locate an assembly and bind to it. On reading this, an obvious question comes to mind. What happens when all of these steps fail to locate the assembly? Does the binder simply quit looking?
It eventually does, but not before firing the AssemblyResolve event. The user can register an event handler for the AssemblyResolve event and then load the assembly that was intended to be loaded in the first place (or execute some other code appropriately).
The AssemblyResolve event itself has been around for a while now. So what’s changed in CLR 4? Prior to CLR 4, if an assembly A has a reference to another assembly B, and an AssemblyResolve event occurs for the referenced assembly (in this case, B), there is no means to know the identity of the parent assembly (or the referencing assembly, or A).
Why is this problematic? Let’s take this example. Let’s assume that an assembly FirstParent.dll references Child.dll. Let’s also assume SecondParent.dll also references Child.dll. On failing to load Child.dll, AssemblyResolve event is fired.
Now, while loading FirstParent.dll and SecondParent.dll using LoadFile(), an AssemblyResolve event is fired for Child.dll. Looking at the AssemblyResolve event, it is unclear as to which parent assembly actually triggered loading Child.dll. This is not helpful if the user wants to execute different code as a part of the ResolveEventHandler, depending on the parent assembly that caused attempting to load Child.dll.
In CLR 4, the AssemblyResolve event provides richer information that includes the parent assembly’s identity. System.ResolveEventArgs now has a property called RequestingAssembly, which is the assembly which requested the (unsuccessful) load of the child assembly, triggering an AssemblyResolve event.
With this new property, when AssemblyResolve event is fired, apart from the current assembly (which could not be located by the Binder), the parent assembly is also provided.
Thus, using this property,
(a) The user now knows which assembly caused the load event
(b) The event handler can now make use of the parent assembly that is passed.
You can read more about this new property here.