如何在应用程序运行时发现新的MEF部件?
我正在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以使用 FileSystemWatcher 检测正在删除的新 DLL在你的插件文件夹中。然后,您可以通过调用 < 来处理此类事件代码>DirectoryCatalog.Refresh 或
AggregateCatalog.Catalogs.Add
< /a> 用新部件更新 MEF 组成。需要注意的一些事项:
您需要将 MEF 导入标记为旨在处理重组,如 重组。否则,当您尝试更新它们时,MEF 将引发错误。
FileSystemWatcher
在系统线程池线程上引发事件(除非您使用SynchronizingObject
属性)。请注意,如果您从另一个线程调用DirectoryCatalog.Refresh
,则必须在启用isThreadSafeFlag
的情况下构造CompositionContainer
。您还必须考虑更新组合时将调用的属性设置器的线程安全性。您还可以通过从
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
orAggregateCatalog.Catalogs.Add
to update the MEF composition with the new parts.Some things to be aware of:
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.
FileSystemWatcher
raises events on system thread pool threads (unless you make use of theSynchronizingObject
property). Be aware that if you callDirectoryCatalog.Refresh
from another thread, you must construct theCompositionContainer
with theisThreadSafeFlag
enabled. You'll also have to think about the thread safety of your property setters that will be called when the composition is updated.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 entireAppdomain
). That also means you still can't delete or overwrite an assembly while the application is running.