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.


So, which one should you use? That depends on which binding context is right for you and whether it matters that the LoadFrom context may redirect the bind. Regarding the latter:



  • If no other code can load assemblies in your AppDomain, your LoadFrom() call can prevent a redirect* by just not loading anything else with a duplicate identity.
  • If you do need to load a duplicate, you could get away with it by loading it into anything other than the LoadFrom context (or into another AppDomain) instead.
  • But, maybe the redirect is really okay. Are they identical assemblies, just at different paths? If yes, it may be safe to risk the redirect unless its dependencies aren’t available in the dir of the first one loaded.
  • Or, are they possibly different bits, just with the same assembly identity? If so, it may be unsafe to risk the redirect: maybe you’ll get an more-updated/not-as-updated version which you didn’t expect. Or, if it’s not strongly-named, maybe this is a third-party’s assembly, totally unrelated to the one you expect.

Comments (12)

  1. Andy Smith says:

    I use LoadFrom() to load an assembly and register the remotable types included therein. I make a call to one of these remotable types from a remote client and it fails UNLESS I put the assembly in the same directory as the host (executable). It’s as if the path that was provided for the LoadFrom() is ignored by the host when it comes time to actually service a remoting call. But this seems odd, doesn’t the assembly stay loaded after my LoadFrom() call? Why would it have to look for the DLL file, since I already loaded it? I must be missing something…

    Thanks!

  2. Suzanne says:

    That’s because remoting’s deserialization causes a call to Assembly.Load(). Since the caller (remoting) is not in the LoadFrom context, it will not be able to automatically find assemblies already loaded there. (Otherwise, the Load context would be order-dependent.) Consider changing to use the Load context instead of LoadFrom, to fix this. See http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx for more info.

    It works when you move the dll to the exe’s dir because that puts the dll in the Load context in the target appdomain, making it findable.

  3. From my tests, LoadWithPartialName has the same semantics as Load. Am I right?

    Thanks

  4. Suzanne says:

    If Load() would have succeeded, they’re the same. If not, LWPN() does a partial bind to assemblies in the GAC. See http://blogs.msdn.com/suzcook/archive/2003/05/30/57159.aspx for why you should never use LWPN().

  5. Commonality says:

    Jon Flanders posts here about a problem he diagnosed recently about Assembly.LoadFrom() and Assembly.Load() behaving differently. The issue he basically…

  6. PainlessProd says:

    I noted on the old blogs site you had some references to Appdomain and loading the current assembly into it. But my problem has to do with referenced assemblies. I noted that assemblies seem to have no problem loading into the correct appdomain and use my shadowcopy, but the assemblies that have references to other assemblies are not being shadow copied. I know you are incredibly busy, but you seem to the only person on the wen that gets this subject. Everything out there seems fairly vague. You can get me at <my Name> at hotmail

  7. prit says:

    from a config file like this

     <!– Create skeleton document –>

           <component type=”Microsoft.Ddue.Tools.CopyFromFileComponent” assembly=”%DXROOT%ProductionToolsBuildComponents.dll”>

             <data file=”%DXROOT%PresentationPrototypetransformsskeleton.xml” />

             <copy source=”/*” target=”/” />

           </component>

    i am using Assembly.LoadFrom() to load the assembly and most oft he entries in my config file point to same assembly like BuildComponents.dll.

    Will there be a huge perf gain if it load otonce and use that refernce than loadign it everytime?

  8. InvalidCastException: Unable to cast object of Type ‘X’ to ‘X’

  9. Mike says:

    In the project i am working on i am using alot of reflection.

    I was having a problem with one of my reflection aspects where i was reading the types from

    foreach(string dll in dllsInBinDirectory)

    {

     Assembly assemb = Assembly.LoadFile(dll)

     readAssembly(assemb);  

    }

    List<ScheduleTask> ScheduleTasks = new List<ScheduleTask>;

    readAssembly(Assembly assemb) {

    foreach(Type t in Assemb.getTypes()) {

    if(type.Base.Name=="ScheduleTask")

    {

    object st = Activator.CreateInstance(type);

    //I was having a problem casting here

    //InvalidCastException: Unable to cast //object /of Type ‘X’ to ‘X’

    scheduleTasks.Add((ScheduleTask)type);

    Even though the object was of the same type, and it seemed like the type was coming from the same Assembly, there locations where different (One Assembly was in the temporary folder) and one was in the Bin folder.

    i found this link

    http://www.infini-tec.de/post/2008/05/InvalidCastException-Unable-to-cast-object-of-Type-X-to-X.aspx

    and Move from Assembly.LoadFile

    to Assembly.LoadFrom

    and it solved! but am i write using it in this context?

    }

    }

    }

  10. Telefisch says:

    Hi Suzanne.

    I’ve a problem binding assemblies to my Excel-C# AddIn.

    I have to do late binding and try this like follows:

    public static object CreateInstanceFromExternalType( string assemblyPath, string typeName )

           {

               try

               {

                   // Externe Assembly laden

                   Environment.CurrentDirectory = System.IO.Path.GetDirectoryName( assemblyPath );

                   Assembly externalAssembly = Assembly.LoadFile( assemblyPath, new Evidence( Assembly.GetExecutingAssembly().Evidence ) );

                   // get Typeinformation

                   Type externalType = externalAssembly.GetType( typeName );

                   // create Instance

                   return Activator.CreateInstance( externalType );

               }

                catch ( Exception ex )

               {

                   throw ex;

               }

           }

    Sometimes this runs and sometimes it crashes.

    My Problem is, that I have to load an assembly from a third party vendor. He says, that his dlls have static linked dependencies and therefore it is absolutely neccessary to lod the original dll.

    obviously excel sometimes loads a temporarily copied dll and then the dependencies are missing.

    Because of your blog I tried to use Assembly.ReflectionOnlyLoadFrom( assemblyPath ) but then Activator.CreateInstance crashes.

    Is there any way to just load the original dll?

    thanks Tele

  11. Thank you for your insight.  It is nice to know the difference between these methods.

    My problem occurs with loadfrom and loadfile.  I get the "Unable to cast object of Type ‘X’ to ‘X’" error when my code that is being ran through reflection tries to access a class that is returned from a web method.  Any suggestions would be appreciated.