Search code examples
c#dynamicdllpluginsmef

Rejecting bad DLL's with MEF


I'm trying to design an extensible GUI application utilizing plugins and MEF.

Now much of it seems to be going according to plan. However, in some cases I'll have a bad DLL which doesn't conform to the contract I've designed. I'd like to be able to tell MEF to ignore the bad DLL and keep everything else in that directory. Is there any way to do this (preferably without deleting the bad DLL)?

I've done some reading and noticed that calling dirCatalog.Parts.ToArray() will help me catch the ReflectionTypeLoadException that is thrown upon the addition of a bad DLL earlier so that I have time to handle it (before adding it to the container). While this helps a bit with debugging purposes, I don't want to crash my program and not load an entire catalog because of one bad DLL.

here's some (unfinished) code that I've come up with.

private void appendToCatalog(DirectoryInfo rootDirInfo)
{
    if (rootDirInfo.Exists)
    {
        DirectoryCatalog dirCatalog = new DirectoryCatalog(rootDirInfo.FullName, Constants.Strings.PLUGIN_EXTENSION);

        try
        {
            // detect a problem with the catalog
            dirCatalog.Parts.ToArray();
        }
        catch (ReflectionTypeLoadException ex)
        {
            // try to remove bad plugins
            filterBadPlugins(dirCatalog);
        }

        catalog.Catalogs.Add(dirCatalog);
    }
}

private void filterBadPlugins(DirectoryCatalog dirCatalog)
{
    foreach (var part in dirCatalog.Parts)
    {
        // This should narrow down the problem to a single part
        Type t = part.GetType(); 
        // need to remove the part here somehow
    }
}

Solution

  • Ultimately, here was my solution. It's not ideal, but it seems to work. I concatenated the filtering method with the append method.

    private void appendToCatalog(DirectoryTreeNode node)
    {
        DirectoryInfo info = node.Info;
        FileInfo[] dlls = info.GetFiles("*.dll");
    
        foreach (FileInfo fileInfo in dlls)
        {
            try
            {
                var ac = new AssemblyCatalog(Assembly.LoadFile(fileInfo.FullName));
                ac.Parts.ToArray(); // throws exception if DLL is bad
                catalog.Catalogs.Add(ac);
            }
            catch
            {
                // some error handling of your choice
            }
        }
    }