This all started because I am trying to FxCop analyze my assembly, which references Crystal Reports. Every time I do, FxCop can't find a reference to an assembly named "BusinessObjects.Licensing.KeycodeDecoder
". In trying to locate this .dll, I've come to realize that it doesn't exist at all... it's not on the hard drive or the GAC, yet my application itself runs and displays reports just fine.
So that led me into some hunting...
In the CrystalDecisions.CrystalReports.Engine.dll
file, if you open it in ILDASM, it does include the reference in its manifest:
.assembly extern BusinessObjects.Licensing.KeycodeDecoder
{
.publickeytoken = (69 2F BE A5 52 1E 13 04 ) // i/..R...
.ver 13:0:2000:0
}
However, if I open the Fusion Logger (fuslogvw) and run my application, I can see Fusion loading a bunch of Crystal assemblies, including that CrystalDecisions.CrystalReports.Engine
, but the referenced BusinessObjects.Licensing.KeycodeDecoder
assembly is never even attempted to be loaded.
So... why? How does the .NET runtime know to skip, or not load that reference at runtime? Why doesn't Fusion just load every referenced assembly recursively? I am just looking for some logic or reasoning or design intentions behind it all...
Perhaps equally as important, why can .NET projects be created that have references to .dlls, but those references aren't enforced? IMO, it is wrong that SAP can ship Crystal assemblies that reference other assemblies that don't even get installed.
It loads them purely on demand. The manifest is used to locate the correct assembly (including the correct version, strong name, etc.).
As long as no one requests a type from the assembly, there is no reason to load it. Note that assemblies might also get loaded just for getting the
Type
of a class, for instance through an assembly-qualified type name in a configuration file.