Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to discover new MEF parts while the application is running?

Tags:

c#

plugins

mef

I'm using MEF to load plugins in my app. Everything works, but I want new parts to be discovered when they are dropped into my app folder. Is this possible? DirectoryCatalog has a Changed event but I'm not sure how it works.

This is my code right now:

public sealed class RevealerFactory
{
    private static readonly Lazy<RevealerFactory> lazy = 
            new Lazy<RevealerFactory>(() => new RevealerFactory());

    public static RevealerFactory Instance { get { return lazy.Value; } }

    private FileSystemWatcher watcher;

    private RevealerFactory()
    {
        Initialize();
    }

    [ImportMany(RequiredCreationPolicy = CreationPolicy.Shared)]
    private IEnumerable<Lazy<IRevealer, IRevealerCapabilities>> Revealers { 
        get;
        set; 
    }

    public IRevealer GetRevealer(Uri uri)
    {
        return (from revealer in Revealers
                where uri.Host.Equals(revealer.Metadata.Host, 
                                      StringComparison.OrdinalIgnoreCase) 
                   && revealer.Value.IsRevelable(uri)
                select revealer.Value).FirstOrDefault();
    }

    private void Initialize()
    {
        var catalog = new DirectoryCatalog(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) 
                                      + "/SDownloader/Revealers");
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }
}
like image 713
David Moreno García Avatar asked Aug 04 '11 15:08

David Moreno García


1 Answers

You can use the FileSystemWatcher to detect new DLLs being dropped in your plugin folder. Then you can handle such events by calling DirectoryCatalog.Refresh or AggregateCatalog.Catalogs.Add to update the MEF composition with the new parts.

Some things to be aware of:

  1. You need to mark your MEF imports as being designed to deal with recomposition, as explained in the MEF programming guide section on Recomposition. Otherwise MEF will raise an error when you try to update them.

  2. FileSystemWatcher raises events on system thread pool threads (unless you make use of the SynchronizingObject property). Be aware that if you call DirectoryCatalog.Refresh from another thread, you must construct the CompositionContainer with the isThreadSafeFlag enabled. You'll also have to think about the thread safety of your property setters that will be called when the composition is updated.

  3. You can also remove catalogs by taking them out of an AggregateCatalog.Catalogs collection. But there is no way to unload the associated assemblies (except by unloading the entire Appdomain). That also means you still can't delete or overwrite an assembly while the application is running.

like image 135
Wim Coenen Avatar answered Oct 05 '22 09:10

Wim Coenen