Switching to the Load Context


So, after checking out the binding context options, you’ve decided to switch your app to use the Load context. Now, you just need to figure out how to do it.


Maybe it will be as simple as using Assembly.Load(assemblyDisplayName) instead of Load(byte[]), etc.  That will work if the assembly is available in the GAC, the AppDomain’s ApplicationBase, or a PrivateBinPath beneath the ApplicationBase. If the assembly is not already in one of those directories, consider changing your deployment strategy.


“I won’t use the GAC because I want to have my own shared path outside of the ApplicationBase” is NOT a good answer! Don’t be afraid to move away from old habits. You’re losing out on all of the benefits of the Load context/versioning and asking for the pain of the other contexts if you don’t. If this is what you’re doing, I recommend putting these in the GAC instead.


  • If the problem is that you don’t want other apps using your assemblies, using a shared path won’t stop them, anyway. Try a Code Access Security solution instead and put them in the GAC.
  • If the problem is that you don’t want to deal with new assembly versions, see my blog entry, When to Change File/Assembly Versions.

 


If it’s really not possible to deploy those assemblies differently, then creating a new appdomain may be right for you.  Create a new AppDomain using an AppDomainSetup.ApplicationBase set to the dir containing the assemblies to load. If you have multiple directories that you want probed, you can set the ApplicationBase to a root directory, and set those as subdirectories to be probed using AppDomainSetup.PrivateBinPath.  If that won’t work for you, consider creating multiple AppDomains, each with the ApplicationBase set to the appropriate dir for its assemblies.


Once you have created the new AppDomain, you will need to find a way to execute code in it. See my blog entry, Executing Code in Another AppDomain for more info.


Note: you can still call LoadFrom() on these assemblies, but they will now be placed in the Load context (as long as they are the first available by that name in the GAC/probing path). However, if at all possible, switch your call to use Assembly.Load() instead of LoadFrom().

Comments (14)

  1. Why don’t you mention "<dependentAssembly>" when you talk about loader features? I think GAC holds entirely differnt semantics than Probing, while <dependentAssembly> and GAC is almost the same. The difference between <dependentAssembly> and GAC is xcopy deployment versus strong name verification. I prefer xcopy, because it is easier to maintain (GAC is more or less .NET’s registry).

  2. Suzanne says:

    Because I don’t want to encourage redirects.

    But, yes, if you keep assemblies local instead of in the GAC, it’s easier for xcopy deployment. However, if you do that on a freshly built app, keeping the assemblies together, using dependentAssembly redirects won’t help you – they’ll hurt perf at best (assuming your AppDomain is set up as recommended).

    And, whoa, the GAC is not like the registry in that it’s version-conscious, etc. (but, yes, that doesn’t help you if you want to xcopy).

  3. First of all, thanks Suzanne for your response. I didn’t mean to redirect assemblies, I just thought about codeBase. Anyway, how much will I hurt performance? Loading will happen once per assembly in an application life cycle and it is far benefitial for us to be maintainable than to be loaded fast-at-first.

    Speaking about GAC and registry, I meant GAC needs registration. Most assemblies we will build will not deserve GAC because it won’t be re-used by others. I think GAC is for system assemblies, like System32 folder is for system dlls. I even want to encourage you to make publisher policy assemblies not necessarily be in the GAC.

    Anyway, I am glad you are in this interactive space. Please keep telling us good stories. Thanks!

  4. Suzanne says:

    Loading by codebase causes an extra permission demand for FileIOPermission.Read and PathDiscovery (or WebPermission, if a web URL). So, using it puts an extra requirement on your app. Plus, loading by codebase when it’s not available otherwise causes the assembly to be loaded in the LoadFrom context. See my blog entry, http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx, about its disadvantages. If your assemblies won’t be shared, then it would be better to put them in the same dir as your exe, and avoid the codebase redirect. If they will be shared, then for xcopy purposes, only, they can be copied to that same dir. But, the shipping app still ought to use them from the GAC.

  5. Hmmm… What you are saying is that,
    – Assemblies that won’t be shared: use probing (therefore LoadFrom context) to load them. If I put them in the same directory as the exe, then the loader find them first anyway, so there’s no such big performance penalty.
    – Assemblies that may be shared: use GAC. dependentAssembly sucks.
    … correct?

    I still don’t get it. My thinking is this. My exe resides in a dir. Dll assemblies that is used by the exe will be in a sub-dir of the exe. Because probing doesn’t consider versioning, I have to use dependentAssembly to determine which sub-dir the dll resides. When dll version-up, then it will be in another sub-dir called V2 and I will distribute new config file and new dll at the same time. This way, when my users have trouble with my applicattion, the only place I have to investigate is my exe folder tree. I know it would be better to use Load context than LoadFrom context. That’s why I use config file and dependentAssembly. GAC is just too far for me to be the place I have to investigate when things go wrong. Am I still missing something?

  6. Suzanne says:

    No, I’m saying try to keep them all in the Load context. Copy the assemblies that won’t be shared to your ApplicationBase (those assemblies will be placed in the Load context). The exe’s dir is the ApplicationBase for the default appdomain, so copying them there is fine, like you suggest.

    Yes, I recommend against redirects (including redirects to a codebase) if you can make the app work without them.

    Right, if you have to use multiple versions of a component, and you want to xcopy, you may be stuck with codebase redirects. But, if you’re using scripts to create new directories, you could just call gacutil from the scripts. But, of course, deploy as you like.

  7. Thanks, now I think I see your point. I thought probed assemblies go into the LoadFrom context since it just uses file name to load, which was wrong. I can’t make up my mind on using GAC or not, but I will certainly give GAC a chance next time. Thanks!

  8. Commonality says:

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

  9. Thanks to Suzanne Cook for this one. &amp;quot;First, obviously, find the two types for which the cast failed,

  10. First, obviously, find the two types for which the cast failed and verify that they are the same type

  11. Rashmi says:

    Hi, I dont have any exe for my application. can i use Application Config file to redirect which assembly to use?

    I am using VS 2008 and VB.NET as coding lang.

    I am facing trouble that inspite “System.Reflection.Assembly.GetExecutingAssembly().Location” gives me the correct assembly location, Assembly loading fails and fusion log suggests that it could not be found.