Assemblies, load context

David Levine asks me how to tell which load context an assembly is in. To my best knowledge, this information is not exposed in managed way. In fact, you don’t even know whether an assembly has a context or not (Remember assemblies returned from Assembly.LoadFile/Assembly.Load(byte[]) do not have a context). This information is not really necesssary for managed applications. All the assemblies returned from various load API have the same functionality available to you. The load context is used for dependency probing. The rule is well defined, and you can’t change the rule after the appdomain is created, and the assembly is returned.

So if the load context is exposed in managed world, it will be purely informational.

But then again, you should already have a pretty good idea about what will be in which load context. Assembly.Load(name) is always in default load context. Assembly.LoadFrom(), and its dependencies will most likely be in loadfrom context. Assembly.LoadFile and Assembly.Load(byte[]) do not have any context.

I know this does not really answer your question. But please post in comments for more questions.

Comments (3)

  1. David Levine says:

    I’ve been waiting for a few days and since no one else has given a reason I’ll give you mine.

    It’s mainly informational and to satisfy my curiousity, but I think it may also lead to useful utilities.

    It would be very handy to know the context because that also can help you lay out appdomains, appbases, private probe paths, redirects, etc. It’s something that would be useful to know as you are developing. It isn’t needed for assemblies I load directly, but instead is for assemblies referenced by the loaded assemblies.

    There is a performance cost when the fusion layer cannot itself satisfy an assembly binding request – it generates an AppDomain.ResolveEvent and the application code gets involved. If the original assembly was loaded from a remote location this can result in a series of probes, each of which occurs over a network – this is very slow. If I can add a private bin path to the appdomain so that the fusion layer finds an assembly, rather then forcing the application code to locate it the performance should be enhanced. Knowing how the fusion layer sees things would help design this.

    It would also be helpful for support purposes to have a utility that can dump the different contexts of a running app. The problem often encountered when debugging/supporting an app is duplicating the environment. Since the fusion contexts are part of the environment it would be useful to know this.

    As an example, I’ve been involved with apps that use multiple appdomains and plugin architectures, and a source of surprise and bugs was related to type identity and type resolution. Since a type definition is bound to an assembly the actual loaded assembly had a major impact on the type.

    For example, this became an issue for us when multiple plugins (installed into separate subdirectories) running in the same appdomain had references to the same type/assembly. Each plugin was separately installed into their own subdirectory along with all the assemblies it referenced; this resulted in several copies of the same assembly in different subdirectories. We wound up in a situation where one instance of the assembly (located in one subdirectory) was in the LoadFrom context and another (located in a different subdirectory) was in the Load context. Basically the same assembly was loaded twice (from different directories), one in the Load context and another in the LoadFrom context, even though it was signed with a strong name and had the identical version – this created exceptions when the type was exchanged between different assemblies. We had to redesign the system as a result.

    I think this knowledge might also lead to better static analysis tools. I’d like to see a tool that looks at an application, its configuration files for redirects, probe paths, etc., and generates a list of expected bindings. It’s helpful to know what bindings cannot be determined from that information.


  2. Thanks for the feedback.

    I know this information is useful for developers. But I want to see how useful it is to warrant an addition.

    In Whidbey we will output the load context in fusion binding log. Assume you turn on fusion binding log, you will be able to know the load context from binding log. This is an indirect way to get this information for developers.

    For your performance concern, if you know your assembly can’t be found by standard probing rule, in Whidbey we have a new appdomain setup property DisallowApplicationBaseProbing. When this property is set, we will never probe the appbase. You will get the AssemblyResolveEvent right after GAC probing. This should address the performance concern.

    The add-in problem you described is a well-known defficiency for LoadFrom. The type cast exception is because CLR loader checks assembly equality based on the file path, not the assembly name. This is unfortunate. A workaround is to install the common dependency to GAC.

    For the static analysis tool, actually Visual Studio is working on one. I told them to use Assembly.Load. It is very very difficult to duplicate fusion’s probing logic. I’ll write another post to show the madness of fusion probing logic.

    Thanks for the question. Keep them coming.

  3. I ran through Suzanne and other folks about this (exposing load context in Assembly class). The feeling is that it is helpful but there is no clear benefit of it. If you have read Raymond’s blog, you know adding things to a platform is not cheap, no matter how trivial the change is.