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

发布于 2024-11-28 07:40:22 字数 1393 浏览 0 评论 0原文

我正在使用 MEF 在我的应用程序中加载插件。一切正常,但我希望当新部件放入我的应用程序文件夹时能够被发现。这可能吗? 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);
    }
}

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);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陪我终i 2024-12-05 07:40:22

您可以使用 FileSystemWatcher 检测正在删除的新 DLL在你的插件文件夹中。然后,您可以通过调用 < 来处理此类事件代码>DirectoryCatalog.RefreshAggregateCatalog.Catalogs.Add< /a> 用新部件更新 MEF 组成。

需要注意的一些事项:

  1. 您需要将 MEF 导入标记为旨在处理重组,如 重组。否则,当您尝试更新它们时,MEF 将引发错误。

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文