Wednesday, September 26, 2007

Assembly Load, LoadFrom, LoadFile

I think I am not very clear about those different loading functions, so I looked up a couple of different sources, and it helps a lot. Here are some understanding I summarized:

  1. If possible, it's better to call Load instead of LoadFrom since the later has to call the first anyway.
  2. LoadFrom actually calls the Load method: Internally, LoadFrom will firstly try to get the AssemblyName by call System.Reflection.AssemblyName.GetAssemblyName( path) method, then it will call Assembly's Load method, passing it the AssemblyName object. If load fails to find an assembly, then LoadFrom loads the assembly at the path name specified in the LoadFrom method. It is possible that there exist two different assemblies which have the same identity, so when LoadFrom internally calls Load, it may load an assembly which is different with the path you specified in the LoadFrom.
  3. LoadFile will load the assembly without CLR applying any policies or searching.
  4. When Load looks for the assembly, it will be based on the following searching path:
    1. GAC
    2. Application's base directory.
    3. Private path subdirectories.
    4. code base locations.
  5. Load has two versions, one is Load(AssembyName), the other is Load(String). When you use the the second method to load, your normally pass in a string like this "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089". Remember, the first section of the string is name, which doesn't include the path and extension. If you choose to use AssemblyName to load, there are three situations.
    1. You didn't specify the codebase, but include other bits. If you don't specify the code base, and set the AssemblyName.Name, CultureInfo, public key token / public key and/or Version properties, it's essentially the same as the Load(String), because you just parse out that string and put it in individual fields.
    2. You specify the codebase, not the name. The code base will have the format look like "file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll", and if you set the codebase, not the name, then, it's doing the same thing as Assembly.LoadFrom() method based on that code base.
    3. When both are specified, then we do step 1 firstly, and if step 1 failed, we do step 2. The thing which worth noting is when you call Assembly.Load(AssemblyName) with a codepath, it does not mean the assembly will be loaded from that path.

References:

Suzanne Cook's .NET CLR Notes

CLR via C#

1 comment:

Sumit said...

Hey, I have an application where there is a scenario where I've got stuck. There are a no. of assemblies which are not required to be installed in GAC. So I tried to use Assembly.LoadFrom to load such assemblies. But the problem came when a requirement to support 2 versions of application came. In this case, there are 2 different paths for 2 different versions of all the application assemblies, and if someone tries to access both the versions, the LoadFrom doesn't work, as it returns the firstly loaded version of a particular dll(say A.dll from C:\Path1) even if I say LoadFrom(C:\Path2\A.dll). This is something which is putting me off. I don't want to install all such DLLs into GAC, as there are about 150 or more such DLLs, and as such they will unnecessarily clutter the GAC. And 150 *2 = 300 Dlls at a single time in GAC. Is there a way out for this situation?