Search code examples
c#wcfmef

Difference between DirectoryCatalog and AssemblyCatalog


I have a MEF application with a fairly large number of components in different dlls. When the program starts up, I create an AggregateCatalog and then load all of the assemblies into it. Due to the large number of components, this can take some time and causes delays in loading the app. I'd like to delay some of the component loading until later, but I've run into a problem. When I load the components using

this.AggregateCatalog.Catalogs.Add(new DirectoryCatalog("."));

I get about 125 components in the catalog and everything runs fine. When I load each dll and exe individually using AssemblyCatalog, I only get about 77 components and the app fails to run due to missing components. I've even created a directory listing and looped through it so that I didn't miss any files and come up with the same result. My question is, What else is DirectoryCatalog doing that allows everything to work properly and how can I emulate it without loading everything in the directory at once?


Solution

  • Difference between AssemblyCatalog and DirectoryCatalog

    I have downloaded the MEF source code from CodePlex (link). By looking at DirectoryCatalog.cs it creates a dictionary Dictionary < string, AssemblyCatalog >() of AssemblyCatalogs, one for each assembly it finds.

        this._assemblyCatalogs = new Dictionary<string, AssemblyCatalog>();
        this._catalogCollection = new ComposablePartCatalogCollection(null, null, null);
    
        this._loadedFiles = GetFiles().ToReadOnlyCollection();
    
        foreach (string file in this._loadedFiles)
        {
            AssemblyCatalog assemblyCatalog = null;
            assemblyCatalog = CreateAssemblyCatalogGuarded(file);
    
            if (assemblyCatalog != null)
            {
                this._assemblyCatalogs.Add(file, assemblyCatalog);
                this._catalogCollection.Add(assemblyCatalog);
            }
        }
    

    As you can see here, it gets all assemblies from a specified directory using GetFiles() (which get all files if no optional search pattern is defined). It then creates a new Assembly catalog for each of those assemblies.

    CreateAssemblyCatalogGuarded add guards for exceptions.

    So as far as I can tell there should not be any differences between using a DirectoryCatalog (which would be my preferred way of doing it) and loading all assemblies in said directory with seperate AssemblyCatalog(s), as this is exactly what DirectoryCatalog does anyway.

    Is it possible there is an error in your code that creates a new AssemblyCatalog for each Assembly ?

    I have also looked at AssemblyCatalog which just loads an Assembly and then gets all it's type.

    Performance problems

    I'd like to delay some of the component loading until later

    If your speed problem happens simply by creating your catalogs, this following bit won't help. Otherwise, if your performance problem happens when you are composing your parts, instead of juggling yourself with AssemblyCatalogs, use MEF Lazy Imports/Exports (Another link). When MEF normally compose parts, it will create instance of all Imports and all child imports. If you defined them as Lazy MEF won't create instances of these types/parts until they are needed (which saves time).