tags:

views:

94

answers:

3

Hi,

AFAIK, there're 3 methods to load an assembly into a AppDomain:

  • Assembly.Load()
  • Assembly.LoadFrom()
  • Assembly.LoadFile()

The LoadFrom() method takes the assembly filepath as its argument, but the filepath is merely providing the assembly identity information as a clue to the CLR. The LoadFrom() method still internally calls Load() with that identity information. So it is quite possible that LoadFrom(filepath) will load a totally different assembly from the one specified by the filepath. But the tame LoadFile() method will just load the assembly we specified.

I am wondering why do we need the LoadFrom() method? It adds nothing but confusion and pitfall. Is there any scenario that only LoadFrom() is applicable?

Many thanks.

A: 

It's quite hidden, and not directly named, but Assembly.LoadFrom loads the assembly from an URI, so you can specify a non-local path; whereas Assembly.Load only loads locally.

This is in the Remarks to LoadFrom:

The assemblyFile parameter must refer to a URI without escape characters. This method supplies escape characters for all invalid characters in the URI.

See msdn

Femaref
+1  A: 

There is actually a lot of discussion about this, with some differing opinions:

http://stackoverflow.com/questions/1477843/difference-between-loadfile-and-loadfrom-with-net-assemblies

http://geekswithblogs.net/rupreet/archive/2010/02/16/137988.aspx

http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/3bdaf65c-520c-4a1a-a825-fc2ca2957bf3

http://blogs.microsoft.co.il/blogs/sasha/archive/2007/03/06/Assembly-Load-Contexts-Subtleties.aspx

To answer your question about why the LoadFrom() method is needed. Well, it seems to come down to wanting to load from a specific location and dependencies. Load() resolves dependencies but does not allow you to choose the location of the assembly (i.e., there is a set "probing" structure on where an assembly is tried to be found). LoadFile() guarantees that you will load the assembly that you specify as the string parameter, but does not resolve dependencies. LoadFrom() doesn't guarantee that the assembly you provide in the path will be loaded (i.e., if an assembly with a similar identity is already loaded), but it does resolve dependencies for you.

From MSDN

Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths. LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. LoadFile is useful in this limited scenario because LoadFrom cannot be used to load assemblies that have the same identities but different paths; it will load only the first such assembly.

From what I have gathered, a shaky consensus seems to form that one should stay away from LoadFile(), use Load() if you can, use LoadFrom() if you need to. But I have seen people say stay away from LoadFrom() too.

As a data point, in the Ecma CLI standard ( http://www.ecma-international.org/publications/standards/Ecma-335.htm ), we only standardized the Assembly.Load(string) method, where the string is an assembly name.

Joel Marcey
+1  A: 

You should always use Assembly.Load(). Only that method can guarantee a predictable outcome. It avoids DLL Hell and ensures an assembly only gets loaded once, even if the code loads it more than once.

You need the other two if you want to intentionally break the rules. LoadFrom() is used if you want to load an assembly that's not in the normal probing path. Pretty common for plug-ins for example when they are stored in a different directory. You'll have no problems getting the intended assembly loaded but you do commonly have a problem with the assemblies that it depends on.

LoadFile() does this as well but also breaks the "don't load it more than once" rule. It is very, very rare that this is what you'd want. Only useful in a case where you'd want to load a copy of an assembly with the same identity but stored in a different path. Some kind of tool that dumps assembly metadata for example. Avoid it in all other cases, it causes nothing but misery. The types loaded from such an assembly are never compatible with the exact same types loaded from another copy of the assembly. Even the same copy.

Hans Passant