如何在应用程序运行时发现新的MEF部件?

Dav*_*cía 12 c# plugins mef

我正在使用MEF在我的应用程序中加载插件.一切正常,但我希望在将它们放入我的app文件夹时发现新的部分.这可能吗?DirectoryCatalog有一个Changed事件,但我不确定它是如何工作的.

这是我现在的代码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Wim*_*nen 21

您可以使用FileSystemWatcher来检测插件文件夹中删除的新DLL.然后,您可以通过调用DirectoryCatalog.RefreshAggregateCatalog.Catalogs.Add使用新部件更新MEF组合来处理此类事件.

有些事情要注意:

  1. 您需要标记您的MEF进口为被专门用来对付重排,如在MEF节目指南部分中说明的重构.否则MEF会在您尝试更新时引发错误.

  2. FileSystemWatcher引发系统线程池线程上的事件(除非您使用该SynchronizingObject属性).请注意,如果DirectoryCatalog.Refresh从另一个线程调用,则必须CompositionContainer使用isThreadSafeFlagenabled 来构造.您还必须考虑在更新合成时将调用的属性设置器的线程安全性.

  3. 您还可以通过目录从AggregateCatalog.Catalogs集合中删除来删除目录.但是没有办法卸载关联的程序集(除了卸载整个程序集Appdomain).这也意味着您仍然无法在应用程序运行时删除或覆盖程序集.

  • 此外,您可以考虑启用卷影复制以允许热交换程序集 (3认同)