1

Contrary to the usual issues of MEF users, I'm not trying to figure out why a dependency of an assembly I load with MEF is not resolved. I am solving the opposite problem - trying to find out why the dependency is loaded.

The situation is that I have an ASP.NET application which uses MEF to dynamically load extension assemblies residing outside the application directory. There may be several versions of the same extension assembly in different directories I probe with MEF, each with its own set of dependencies and these dependencies again may be multiple versions of a single assembly (i.e. extension A.dll, 1.0.0.0 has a dependency D.dll, 1.0.0.0 and an extension B.dll, 2.0.0.0 has a dependency D.dll, 2.0.0.0).

It works in a sense that all the extensions and all their dependencies are loaded correctly. And I don't know why. I have no special settings in my web.config file. Where in the official documentation on assembly resolving does it say that it should work? It doesn't say anything about looking at the same directory the requesting assembly is located at.

I was hoping the Fusion Log Viewer would tell me how the runtime locates the dependencies but even though it shows me the binding requests for all the different versions of a given dependency, when I click on it to see the full log, I only see failed bindings (and yes, I have it set to log all binding requests, not just the failed ones).

Can anyone point me to the part of an official documentation explaining why this scenario works?

twoflower
  • 6,788
  • 2
  • 33
  • 44
  • They're not in GAC. When I see the loaded modules in `Debug` -> `Windows` -> `Modules`, I can see they are loaded from the same directories the MEF-loaded assemblies reside at. – twoflower Oct 25 '13 at 17:10

1 Answers1

1

The main resolution with MEF is determined by the ComposablePartCatalog used. For example, if you use DirectoryCatalog, all assemblies within the specified directory get probed and found.

By looking at the CompositionContainer, you should be able to find the catalogs that are in place, which in turn should provide some details as to why the parts are composing properly.

It is also possible that your dependencies are being found due to the rules defined in "Other Locations Probed":

If an assembly uses the LoadFrom method to reference another assembly, the calling assembly's location is considered to be a hint about where to find the referenced assembly. If a match is found, that assembly is loaded.


If you are using a DirectoryCatalog to find the assemblies within a directory, it internally loads every assembly within that folder. This will cause all of your dependencies to also be loaded into the process when the DirectoryCatalog is constructed.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Thank you Reed. Yes, I use the `DirectoryCatalog`. The extension assemblies do not use `LoadFrom`, their dependencies are ordinary static references. About the `DirectoryCatalog` - are the dependencies loaded in the process of trying to resolve them (I would say not) or are they loaded just because MEF needs to check whether they export some of the interfaces I'm interested in? – twoflower Oct 25 '13 at 17:15
  • @twoflower I believe (not 100% sure here) that they get loaded because the dependency is loaded via `LoadFrom`, which in turn causes their directory to become a probing hint. – Reed Copsey Oct 25 '13 at 17:20
  • You mean MEF is calling `LoadFrom` explicitly? I was living under the impression that MEF doesn't do anything special about locating dependencies and saw it mentioned several times. I'm going to check the MEF's source code and see if I can figure it out there. – twoflower Oct 25 '13 at 17:23
  • Oh, I probably see now what you meant, disregard my previous comment. But looking at the MEF source code now, it seems it doesn't use `LoadFrom` when using `DirectoryCatalog`, instead it seems it uses `Load(AssemblyName)` which doesn't explain why the dependencies are loaded. – twoflower Oct 25 '13 at 17:40
  • Another possibility is that all the assemblies in the directory are loaded and all of them are kept loaded though only some of them export something of interest. But that seems like a weird thing to do. – twoflower Oct 25 '13 at 17:45
  • @twoflower Just checked the code - DirectoryCatalog loads every assembly in the folder... Will edit. – Reed Copsey Oct 25 '13 at 17:51
  • Good, now we're sure each assembly in the directory gets loaded by MEF. But, as I already wrote in my previous comment, what's the motivation of *keeping* all the assemblies loaded if only some of them provide the exports I'm interested in? Is this so to satisfy the (possibly common) case of having extension assemblies along with all their dependencies in the same directory? – twoflower Oct 25 '13 at 17:56
  • @twoflower Probably - but in .NET, once you load an assembly, there's no way to unload it (other than unloading the entire AppDomain) - it was very likely done just because there isn't an easy way to avoid it ;) – Reed Copsey Oct 25 '13 at 17:58
  • Ah, that explains it :-) Thank you very much for a great answer, Reed! – twoflower Oct 25 '13 at 18:00
  • @twoflower Load(AssemblyName) can load an assembly in the LoadFrom context if only the CodeBase property is used. This is what AssemblyCatalog.LoadAssembly is doing. – Panos Rontogiannis Oct 26 '13 at 19:49