146

I was looking at the msdn documentation and I am still a little confused on what exactly is the difference between using LoadFile and LoadFrom when loading an assembly. Can someone provide an example or an analogy to better describe it. The MSDN documentation confused me more. Also, Is ReflectionOnlyLoadFrom the same as LoadFrom except that it loads the assembly only in reflection mode.

Since my .NET experience is not the greatest, here are some questions regarding the MSDN documentation using LoadFile:

1) What does it mean by LoadFile examines assemblies that have the same Identity, but are located in different paths? What is the identity (example)?

2) It states the LoadFile does not load files into the 'LoadFrom Context' and does not resolve dependencies using the load path. What does this mean, can someone provide an example?

3) Lastly, it states that LoadFile is useful in this limited scenario because LoadFrom cannot load assemblies that have the same identities but different paths; it will only load the first such assembly, which again brings me to the same question, what is the assemblies identity?

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Xaisoft
  • 45,655
  • 87
  • 279
  • 432
  • 10
    Seriously I also think sometimes that MS should hire better writers or something else since the sentences are not always comprehensible... – Tarik Mar 31 '12 at 17:14
  • 9
    See also [*undocumentation*](http://www.codinghorror.com/blog/2005/11/avoiding-undocumentation.html) – Colonel Panic Apr 26 '13 at 14:33
  • 3
    @ColonelPanic MS can say that everything is documented... but with a help factor of zeroooo. – Legends Jan 08 '17 at 15:28

7 Answers7

108

Does this clear it up?

// path1 and path2 point to different copies of the same assembly on disk:

Assembly assembly1 = Assembly.LoadFrom(path1);
Assembly assembly2 = Assembly.LoadFrom(path2);

// These both point to the assembly from path1, so this is true
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);

assembly1 = Assembly.LoadFile(path1);
assembly2 = Assembly.LoadFile(path2);

// These point to different assemblies now, so this is false
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);

Edit: to answer the questions you raised in your revised question, you definitely want to read Suzanne Cook on Assembly Identity.

There are a lot of rules that govern how assemblies are loaded, and some of them have to do with how they resolve dependencies - if your AssemblyA is dependent on AssemblyB, where should .NET look to find AssemblyB? In the Global Assembly Cache, the same directory it found AssemblyA, or somewhere else entirely? Furthermore, if it finds multiple copies of that assembly, how should it choose which one to use?

LoadFrom has one set of rules, while LoadFile has another set of rules. It is hard to imagine many reasons to use LoadFile, but if you needed to use reflection on different copies of the same assembly, it's there for you.

Lukas
  • 2,461
  • 2
  • 19
  • 32
Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
  • 2
    Is the CodeBase the same as the Identity? – Xaisoft Sep 25 '09 at 15:20
  • No, I just used CodeBase here as an arbitrary property of the assembly to illustrate that the second Assembly instance was pointing to the 'wrong' file (in the first example). I'm updating my answer with more details. – Jeff Sternal Sep 25 '09 at 15:24
  • 1
    It clears it up a bit, but how does path1 and path2 point to different copies of the same assembly on disk when using LoadFrom and when using LoadFile, path1 and path2 point to different assemblies. What is an example of what path1 and path2 would be? Thanks for your patience. – Xaisoft Sep 25 '09 at 15:27
65

From Suzanne Cook's blog:

LoadFile vs. LoadFrom

Be careful - these aren't the same thing.

LoadFrom() goes through Fusion and can be redirected to another assembly at a different path but with that same identity if one is already loaded in the LoadFrom context.

LoadFile() doesn't bind through Fusion at all - the loader just goes ahead and loads exactly* what the caller requested. It doesn't use either the Load or the LoadFrom context.

So, LoadFrom() usually gives you what you asked for, but not necessarily. LoadFile() is for those who really, really want exactly what is requested. (*However, starting in v2, policy will be applied to both LoadFrom() and LoadFile(), so LoadFile() won't necessarily be exactly what was requested. Also, starting in v2, if an assembly with its identity is in the GAC, the GAC copy will be used instead. Use ReflectionOnlyLoadFrom() to load exactly what you want - but, note that assemblies loaded that way can't be executed.)

LoadFile() has a catch. Since it doesn't use a binding context, its dependencies aren't automatically found in its directory. If they aren't available in the Load context, you would have to subscribe to the AssemblyResolve event in order to bind to them.

See here.

Also see Choosing a Binding Context article on the same blog.

mdonoughe
  • 515
  • 5
  • 12
CraigTP
  • 44,143
  • 8
  • 72
  • 99
  • Thanks, I will check out the blog, I updated my post with some questions regarding the msdn documentation. – Xaisoft Sep 25 '09 at 15:19
  • @Xaisoft - Suzanne Cook's blog comes to the rescue again with the answer of an Assemblies Identity. See http://blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx. It is essentially an "assembly display name" and this is something like: "System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" so includes both the assembly's actual name, it's version number along with other identifying information (like PublicKeyToken etc.). – CraigTP Sep 25 '09 at 15:28
  • Curious, is Suzanne Cook the Reflection Guru :) – Xaisoft Sep 25 '09 at 15:29
  • 1
    What is she referring to when she talks about Fusion? – Xaisoft Sep 25 '09 at 15:36
  • Fusion is the .NET sub-system that locates and loads assemblies, and Suzanne Cook is its Guru. (Probably a general Reflection Guru too.) :) – Jeff Sternal Sep 25 '09 at 15:49
  • 1
    Indeed, Jeff is spot on. See this link: http://www.grimes.demon.co.uk/workshops/fusionWS.htm for a nice tutorial on the Fusion sub-system and it's technology for loading assemblies in .NET – CraigTP Sep 25 '09 at 18:34
  • 1
    Just a quick update, note that the URL above (grimes.demon.co.uk/workshops/fusionWS.htm) is no longer valid and has now moved to: http://www.richardgrimes.com/workshops/fusionWS.htm – CraigTP Aug 20 '12 at 08:08
52

After a lot of head-scratching I've discovered a difference myself this afternoon.

I wanted to load a DLL at runtime, and the DLL lived in another directory. That DLL had its own dependencies (DLLs) which also lived in that same directory.

LoadFile(): Loaded the specific DLL, but not the dependencies. So when the first call was made from within the DLL to one of those other DLLs it threw a FileNotFoundException.

LoadFrom(): Loaded the DLL that I specified and also all the dependencies that lived in that directory.

LordWilmore
  • 2,829
  • 2
  • 25
  • 30
  • 4
    That was exactly my problem! I was getting the `FileNotFoundException` when creating a new instance of an object defined in an assembly referenced by the assembly I had just loaded with `.LoadFile`. Changing this to `.LoadFrom` appeared to fix the issue, but I didn't know why! Thanks – Connell Jun 25 '13 at 11:57
  • But `LoadFrom` and `LoadFile` are different. So you cannot just replace those two – Zoli Jun 01 '22 at 14:23
  • @zoli that's correct, and my post explains the differences and why they are not interchangeable – LordWilmore Jun 01 '22 at 18:18
4

Note: If one assembly is loaded using an 8.3 path, and then from a non-8.3 path, they will be seen as different assemblies, even though they are the same physical DLL.

1

.NET has different load context. Suzanne Cook wrote about them here: https://learn.microsoft.com/en-us/archive/blogs/suzcook/choosing-a-binding-context

This is the way .NET quarantines that references are not mixed up.

Pang
  • 9,564
  • 146
  • 81
  • 122
Arthur
  • 7,939
  • 3
  • 29
  • 46
0

In my case, I just had to simply delete the ASP application cache located @ C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files. It is rebuilt when the site is first run. Be sure to stop IIS first.

Hope this helps someone like it did for me.

David Roth
  • 87
  • 3
  • 8
-2

one difference that i noticed is:

Assembly.LoadFile - Loads assembly in different AppDomain with limited user rights (diffrence principel). operations like serilization/deserilization could not be performed.

Assembly.LoadFrom- Loads assembly in same AppDomain with same user rights (same principel).

Lalit
  • 4,897
  • 7
  • 32
  • 36
  • 5
    This is not correct. What makes you believe that Assembly.LoadFile loads an assembly into another AppDomain? – Sven Mawby Mar 30 '18 at 15:51