Choosing a Binding Context

There are three 'contexts' for assembly binding:

  • Load context
    In general, if the assembly was found by probing in the GAC, a host assembly store (if hosted), or the ApplicationBase / PrivateBinPaths of the AppDomain, the assembly will be loaded in the Load context.
  • LoadFrom context
    In general, if the user provided Fusion a path which was used to find the assembly (and the assembly at that path wouldn't have been found in the Load context), then it's in the LoadFrom context. There are various methods to load by path: LoadFrom(), CreateInstanceFrom(), ExecuteAssembly(), loading an assembly through interop using a codebase, etc.
  • Neither
    If the user generated or found the assembly instead of Fusion, it's in neither context. This applies to assemblies loaded by Assembly.Load(byte[]) and Reflection Emit assemblies (that haven't been loaded from disk). Assembly.LoadFile() assemblies are also generally loaded into this context, even though a path is given (because it doesn't go through Fusion).

Which context is right for you? In general, I strongly recommend that you use the Load context whenever possible. But, of course, there will be times when other contexts are more appropriate for you. So, here are the advantages and disadvantages of each option:

  Advantages Disadvantages
Load
  • Gets the benefits of versioning and policy.
  • Best avoids "Dll Hell." Dll Hell can break your app over time.
  • Dependencies available in the Load context are automatically found.
  • Dependencies in other contexts are not available unless you subscribe to the AppDomain.AssemblyResolve event.
LoadFrom
  • Assemblies can be loaded from multiple paths, not just from beneath the ApplicationBase.
  • Dependencies already loaded in this context will automatically be found.
  • Dependencies in the same dir as the requesting LoadFrom context assembly will automatically be found.
  • If a Load context assembly tries to load this assembly by display name, it will fail to be found by default (e.g., when mscorlib.dll deserializes this assembly).
  • Worse, an assembly with the same identity but at a different path could be found on the probing path, causing an InvalidCastException, MissingMethodException, or unexpected method behavior later on.
  • If an assembly by the same identity is already loaded, you'll get that one back, even if you've specified a path to a different one.
  • It does a FileIOPermission.Read + PathDiscovery demand, or a WebPermission demand on the path/URL specified.
  • The ngen image (if any) won't be used.
  • Can't be loaded as domain-neutral.
  • v1.0 and v1.1 CLR only: won't be affected by policy, so can't be centrally serviced.
Neither
  • Avoids probing costs for loading this assembly.
  • You can load multiple assemblies with the same identity into the same appdomain.
  • You get the bits from the location you specified (as opposed to LoadFrom). Starting in v2, policy/GAC overrides it, however.
  • Nothing can bind to this assembly unless you've subscribed to the AssemblyResolve event.
  • Dependencies can only be loaded from the Load context or using the AssemblyResolve event.
  • Passing this assembly to another AppDomain may become tricky (e.g., when this is a Reflection Emit assembly that hasn't been saved).
  • The ngen image (if any) won't be used.
  • Can't be loaded as domain-neutral.
  • v1.0 and v1.1 CLR only: won't be affected by policy, so can't be centrally serviced.

Comments

  • Anonymous
    May 30, 2003
    What changes, if anything, if I subscrive to AssemblyResolve and resolve original Load() calls with LoadFrom()Thanks

  • Anonymous
    May 30, 2003
    I found the load articles here are very helpful to my work. Thanks.I don't quite understand one statment in the table though. It is the first item in LoadFrom, DisAdvantages:"If a Load context assembly tries to load this assembly by display name, it will fail by default (e.g., when mscorlib.dll deserializes this assembly). " What does it mean, could you give an more detailed example?

  • Anonymous
    June 03, 2003
    The AssemblyResolve event just passes the already-loaded Assembly around. If it was loaded in the LoadFrom context (or whatever), it will remain there - no changes.

  • Anonymous
    June 03, 2003
    The comment has been removed

  • Anonymous
    April 08, 2004
    Hi Suzannne (great log).

    What is the difference (if there is any) beetween:
    Assembly.Load(AsssemblyName.GetAssemblyName(path))

    and

    Assembly.LoadFrom(path);

    It seems to be that the first is better...
    Simon.

  • Anonymous
    April 13, 2004
    Thanks. The difference is that the the first one may load that assembly at a different path than the one specified, if it's available in the Load context. Also, in that case, it causes policy to be applied when it would not have been for LoadFrom() (pre-v2.0).

    Also consider the performance implications of the first one: it may cause the file to be loaded and unloaded, when it's going to be immediately loaded, anyway. Plus, it may cause extra probing by display name. If the ApplicationBase starts with "http:", that would cause a possibly significant delay.

  • Anonymous
    May 20, 2004
    We have a light exe on the client machine that calls Assembly.LoadFrom to No Touch Deploy our assemblies from a web server. If I understand you, calling Load may help our performance. We already handle the AssemblyResolve in this light exe:

    AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf AssemblyResolve

    I would appreciate your feedback on this: greg@cds-am.net

  • Anonymous
    July 25, 2004
    Hi,

    I am using the probing in my app.config. Even though LoadFrom is not working . Can any body give suggestions

    Regards
    -Roopesh

  • Anonymous
    October 04, 2004
    Jon Flanders posts here about a problem he diagnosed recently about Assembly.LoadFrom() and Assembly.Load() behaving differently. The issue he basically...

  • Anonymous
    May 20, 2005
    Is there any known problems with calling LoadFrom() from one Forms application to start another Forms application in a different thread.

    I have an applicaton with a simple [Serializable] struct. In this app I have a function that serializes and deserializes the struct. It works fine if I call the function when the process is started normally, but if it is called from a thread created by a different assembly I get either:

    SerializationException: Cannot find the assembly ...

    or if I put the assembly with that serialzation stuff in the same directory with the application that creates the thread I get:

    InvalidCastException: Specified cast is not valid.

  • Anonymous
    June 22, 2005
    The comment has been removed

  • Anonymous
    July 05, 2005
    I recently ran into the problem with the AssemblyResolve event in the AppDomain. Basically, multiple threads were concurrently firing this event, and multiple instances of the same assembly (binary the same, but differenct instances) were loaded. The end result was that I received the MethodMissingException and chased it for about a week. Long story short, I now have a lock in the class that handles this event, and I have to keep a look aside hashtable with WeakReferences to the assembly. I don't keep direct references because I want to enable the unloading of the Assembly from the AppDomain if desired

  • Anonymous
    September 21, 2005
    Hello,

    I am running into specified cast error and I posted the question on the forum. I ran into this error only after upgrading to Windows 2003 SP1 which I believe also installs .NET framework 1.1 SP1.

    http://groups.google.co.in/group/microsoft.public.dotnet.framework.aspnet/browse_frm/thread/1427cdfa08ee5efd/ad4f9ef611969749?tvc=1&q=%22Shade+some+light%22&hl=en#ad4f9ef611969749

    Can you please look at the thread and repond?

    Thanks.
    -Prasad

  • Anonymous
    November 07, 2005
    The comment has been removed

  • Anonymous
    November 29, 2005
    Help required on running 1.1 binaries in 2.0

    Hi,
    We've built the binaries under 1.1 environment and they are running fine on a machine with 1.1 and 2.0 environments. But when the same binaries are built in 2.0 environment, following errors are seen. Any idea how to resolve them.

    'Managed': Loaded 'F:WindowsassemblyGAC_32mscorlib2.0.0.0__b77a5c561934e089mscorlib.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    'Managed': Loaded 'C:servicetestIpfilterEngine.exe', Symbols loaded.
    'Managed': Loaded 'C:servicetestutility.dll', Symbols loaded.
    'Managed': Loaded 'F:WindowsassemblyGAC_MSILSystem2.0.0.0__b77a5c561934e089System.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    'Managed': Loaded 'F:WindowsassemblyGAC_MSILSystem.Xml2.0.0.0__b77a5c561934e089System.Xml.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    'Managed': Loaded 'F:WindowsassemblyGAC_MSILSystem.Configuration2.0.0.0__b03f5f7f11d50a3aSystem.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    Managed Debugging Assistant 'BindingFailure' has detected a problem in 'C:servicetestIpfilterEngine.exe'.

    Additional Information: The assembly with display name 'ipfilterengine.XmlSerializers' failed to load in the 'LoadFrom' binding context of the AppDomain with ID 1. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'ipfilterengine.XmlSerializers, Version=6.0.5268.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
    File name: 'ipfilterengine.XmlSerializers, Version=6.0.5268.0, Culture=neutral, PublicKeyToken=null'

    === Pre-bind state information ===
    LOG: User = SRA-STRESS-1Administrator
    LOG: DisplayName = ipfilterengine.XmlSerializers, Version=6.0.5268.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL
    (Fully-specified)
    LOG: Appbase = file:///C:/servicetest/
    LOG: Initial PrivatePath = NULL
    Calling assembly : System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
    ===
    LOG: This bind starts in default load context.
    LOG: No application configuration file found.
    LOG: Using machine configuration file from F:WindowsMicrosoft.NETFrameworkv2.0.50727configmachine.config.
    LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers.DLL.
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers/ipfilterengine.XmlSerializers.DLL.
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers.EXE.
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers/ipfilterengine.XmlSerializers.EXE.
    Managed Debugging Assistant 'BindingFailure' has detected a problem in 'C:servicetestIpfilterEngine.exe'.

    Additional Information: The assembly with display name 'ipfilterengine.XmlSerializers' failed to load in the 'Load' binding context of the AppDomain with ID 1. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'ipfilterengine.XmlSerializers' or one of its dependencies. The system cannot find the file specified.
    File name: 'ipfilterengine.XmlSerializers'

    === Pre-bind state information ===
    LOG: User = SRA-STRESS-1Administrator
    LOG: DisplayName = ipfilterengine.XmlSerializers
    (Partial)
    LOG: Appbase = file:///C:/servicetest/
    LOG: Initial PrivatePath = NULL
    Calling assembly : System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
    ===
    LOG: This bind starts in default load context.
    LOG: No application configuration file found.
    LOG: Using machine configuration file from F:WindowsMicrosoft.NETFrameworkv2.0.50727configmachine.config.
    LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers.DLL.
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers/ipfilterengine.XmlSerializers.DLL.
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers.EXE.
    LOG: Attempting download of new URL file:///C:/servicetest/ipfilterengine.XmlSerializers/ipfilterengine.XmlSerializers.EXE.
    'Managed': Loaded 'C:servicetestremoteserver.dll', Symbols loaded.
    'Managed': Loaded 'igg8sw7i', No symbols loaded.
    Managed Debugging Assistant 'BindingFailure' has detected a problem in 'C:servicetestIpfilterEngine.exe'.

    Additional Information: The assembly with display name 'ipfilterengine.XmlSerializers' failed to load in the 'LoadFrom' binding context of the AppDomain with ID 1. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'ipfilterengine.XmlSerializers, Version=6.0.5268.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
    File name: 'ipfilterengine.XmlSerializers, Version=6.0.5268.0, Culture=neutral, PublicKeyToken=null'

    === Pre-bind state information ===
    LOG: User = SRA-STRESS-1Administrator
    LOG: DisplayName = ipfilterengine.XmlSerializers, Version=6.0.5268.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL
    (Fully-specified)
    LOG: Appbase = file:///C:/servicetest/
    LOG: Initial PrivatePath = NULL
    Calling assembly : System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
    ===
    LOG: This bind starts in default load context.
    LOG: No application configuration file found.
    LOG: Using machine configuration file from F:WindowsMicrosoft.NETFrameworkv2.0.50727configmachine.config.
    LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
    LOG: The same bind was seen before, and was failed with hr = 0x80070002.
    Managed Debugging Assistant 'BindingFailure' has detected a problem in 'C:servicetestIpfilterEngine.exe'.

    Additional Information: The assembly with display name 'ipfilterengine.XmlSerializers' failed to load in the 'Load' binding context of the AppDomain with ID 1. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'ipfilterengine.XmlSerializers' or one of its dependencies. The system cannot find the file specified.
    File name: 'ipfilterengine.XmlSerializers'

    === Pre-bind state information ===
    LOG: User = SRA-STRESS-1Administrator
    LOG: DisplayName = ipfilterengine.XmlSerializers
    (Partial)
    LOG: Appbase = file:///C:/servicetest/
    LOG: Initial PrivatePath = NULL
    Calling assembly : System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
    ===
    LOG: This bind starts in default load context.
    LOG: No application configuration file found.
    LOG: Using machine configuration file from F:WindowsMicrosoft.NETFrameworkv2.0.50727configmachine.config.
    LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
    LOG: The same bind was seen before, and was failed with hr = 0x80070002.
    'Managed': Loaded 'sxj1yu2h', No symbols loaded.
    'Managed': Loaded 'F:WindowsassemblyGAC_MSILSystem.Runtime.Remoting2.0.0.0__b77a5c561934e089System.Runtime.Remoting.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    The thread 0xadc has exited with code 0 (0x0).
    The thread 0xddc has exited with code 0 (0x0).
    The thread 0xe1c has exited with code 0 (0x0).
    The program '[2996] IpfilterEngine.exe: Managed' has exited with code 0 (0x0).

  • Anonymous
    December 08, 2005
    The comment has been removed

  • Anonymous
    June 12, 2006
    The comment has been removed

  • Anonymous
    August 14, 2006
    The problem I am experiencing is with LoadFrom.

    On a development machine, LoadFrom is resolving dependencies. After deploying, I can debug remotely, and watch LoadFrom load the correct module. At this point in our code we attempt to create an instance of a type in a dependent assembly. On a development machine, I can see that this new assembly is loaded up correctly, but in the deployed version, no dependencies are loaded up, and an error is thrown.

    LoadFrom is supposed to check the path of this newly loaded assembly for dependencies, which it correctly does on a development machine, but fails in our deployed version.

    We are developing against the 2.0 framework ( 2.0.50727.42 ).

  • Anonymous
    August 15, 2006
    Thanks to Suzanne Cook for this one. "First, obviously, find the two types for which the cast failed,

  • Anonymous
    March 15, 2007
    AppDomain.AssemblyResolve - Cool, but dangerous ... just the way I like my coffee

  • Anonymous
    April 12, 2007
    Calling Load(AssemblyName) is not necessarily the same as calling Load(String). If the AssemblyName.CodeBase

  • Anonymous
    April 12, 2007
    First, obviously, find the two types for which the cast failed and verify that they are the same type

  • Anonymous
    April 12, 2007
    Be careful - these aren't the same thing. LoadFrom() goes through Fusion and can be redirected to another

  • Anonymous
    April 12, 2007
    I hesitate to talk about this because I don't want people who don't know about it to think, "Hey, what's

  • Anonymous
    April 12, 2007
    There are two types of assembly identity that the loader deals with: bind-time and after bind-time. The

  • Anonymous
    April 12, 2007
    So, after checking out the binding context options , you've decided to switch your app to use the Load

  • Anonymous
    April 30, 2007
    Suzanne, I've looked around but i can't seem to find a concise doc about this: I'm using AssemblyResolve in an assembly that is consumed by an ASP.NET web service. Seems that my AssemblyResolve subscription is never being fired. Is asp.net listening to that event also and possibly stepping in front of my assembly? What are my options?  I really want to use a .Load(Byte[]) method so that i can deliver my assembly as a single file.  I want to do it this way to protect the code inside from being decompiled/inspected. Regards, Eriq

  • Anonymous
    February 04, 2008
    Awesome post ... helped me lot to solve my problem

  • Anonymous
    October 07, 2008
    Excellent post -- thanks for the help.

  • Anonymous
    January 15, 2009
    The comment has been removed

  • Anonymous
    March 26, 2009
    Excellent post -- It's rare to find a post which really gives insight, rather than a laundry list of try-this-and-see-if-it-works items.  Very refreshing.  Very well done.  Thanks for this. -Alan.