我在MEF Codeplex论坛上已经提出这个问题,但我还没有得到答复,所以我想我会尝试StackOverflow。这里是原来的职位,如果任何人的兴趣(这只是一个从它复印件):MEF +插件没有更新
“让我先说,我完全新的MEF(今天才发现了它),我非常高兴但是,我遇到了一个非常令人沮丧的问题,我创建了一个具有插件体系结构的应用程序,插件只会存储在一个DLL文件中(或者编码到主应用程序中)。DLL文件需要能够在运行时重新编译,应用程序应该识别这个并重新加载插件(我知道这很困难,但这是一项要求)。为了实现这一点,我采取了包括http://blog.maartenballiauw.be/category/MEF.aspx那里(寻找WebServerDirectoryCatalog)。基本上这个想法是“监控插件文件夹中,将新的/修改过的程序集复制到Web应用程序的/ bin文件夹中,并指示MEF从那里加载它的导出。“这是我的代码,可能不是正确的方法,但这是我在某些示例中发现的净:
main()...
string myExecName = Assembly.GetExecutingAssembly().Location;
string myPath = System.IO.Path.GetDirectoryName(myExecName);
catalog = new AggregateCatalog();
pluginCatalog = new MyDirectoryCatalog(myPath + @"/Plugins");
catalog.Catalogs.Add(pluginCatalog);
exportContainer = new CompositionContainer(catalog);
CompositionBatch compBatch = new CompositionBatch();
compBatch.AddPart(this);
compBatch.AddPart(catalog);
exportContainer.Compose(compBatch);
和
private FileSystemWatcher fileSystemWatcher;
public DirectoryCatalog directoryCatalog;
private string path;
private string extension;
public MyDirectoryCatalog(string path)
{
Initialize(path, "*.dll", "*.dll");
}
private void Initialize(string path, string extension, string modulePattern)
{
this.path = path;
this.extension = extension;
fileSystemWatcher = new FileSystemWatcher(path, modulePattern);
fileSystemWatcher.Changed += new FileSystemEventHandler(fileSystemWatcher_Changed);
fileSystemWatcher.Created += new FileSystemEventHandler(fileSystemWatcher_Created);
fileSystemWatcher.Deleted += new FileSystemEventHandler(fileSystemWatcher_Deleted);
fileSystemWatcher.Renamed += new RenamedEventHandler(fileSystemWatcher_Renamed);
fileSystemWatcher.IncludeSubdirectories = false;
fileSystemWatcher.EnableRaisingEvents = true;
Refresh();
}
void fileSystemWatcher_Renamed(object sender, RenamedEventArgs e)
{
RemoveFromBin(e.OldName);
Refresh();
}
void fileSystemWatcher_Deleted(object sender, FileSystemEventArgs e)
{
RemoveFromBin(e.Name);
Refresh();
}
void fileSystemWatcher_Created(object sender, FileSystemEventArgs e)
{
Refresh();
}
void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
Refresh();
}
private void Refresh()
{
// Determine /bin path
string binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");
string newPath = "";
// Copy files to /bin
foreach (string file in Directory.GetFiles(path, extension, SearchOption.TopDirectoryOnly))
{
try
{
DirectoryInfo dInfo = new DirectoryInfo(binPath);
DirectoryInfo[] dirs = dInfo.GetDirectories();
int count = dirs.Count() + 1;
newPath = binPath + "/" + count;
DirectoryInfo dInfo2 = new DirectoryInfo(newPath);
if (!dInfo2.Exists)
dInfo2.Create();
File.Copy(file, System.IO.Path.Combine(newPath, System.IO.Path.GetFileName(file)), true);
}
catch
{
// Not that big deal... Blog readers will probably kill me for this bit of code :-)
}
}
// Create new directory catalog
directoryCatalog = new DirectoryCatalog(newPath, extension);
directoryCatalog.Refresh();
}
public override IQueryable<ComposablePartDefinition> Parts
{
get { return directoryCatalog.Parts; }
}
private void RemoveFromBin(string name)
{
string binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "");
File.Delete(Path.Combine(binPath, name));
}
所以这一切的实际工作,并在主我的IEnumerable变量的代码结束后竟充满DLL中所有的插件(其中,如果你请按照代码位于插件/ 1,以便我可以修改插件文件夹中的DLL)。 因此,现在我应该能够重新编译插件DLL,将它放入Plugins文件夹,我的FileWatcher检测到它已更改,然后将其复制到文件夹“2”中,并且directoryCatalog应该指向新文件夹。所有这些 实际上工作!问题是,尽管看起来每件事都指向了正确的位置,但我的IEnumerable变量永远不会被新的插件更新。如此接近,但迄今为止!有什么建议么? 我知道这样做的缺点,没有DLL实际上是卸载并导致内存泄漏,但它是一个Windows应用程序,并可能会启动至少每天一次,并且插件不可能更改 通常情况下,但它仍然是客户的要求,它在不重新加载应用程序的情况下执行此操作。谢谢!
感谢您的帮助,您都可以提供,它的驾驶我疯狂不能够想出解决办法“。
感谢您的回复,但我不明白这对我有何帮助。在更多地使用MEF之后,似乎我可以将我的目录实现更改为基本的存储类,并且摆脱ComposablePartCatalog,因为我已经有了一个directoryCatalog。 DirectoryCatalog确实实现了INotifyComposablePartCatalogChanged,这对我来说意味着它应该正确地更新东西,如果我将主代码更改为catalog.Catalogs.Add(pluginCatalog.directoryCatalog);. – user64718 2010-04-13 03:13:24
@mybrokengnome:如果将'pluginCatalog.directoryCatalog'更改为新的,MEF容器不会奇迹般地注意到。它仍然会听取更改旧通知的通知。在我看来,变更通知与您的问题非常相关;它怎么会不是? – 2010-04-13 08:54:49
我没有改变它的情况下,它现在总是指向pluginCatalog.directoryCatalog(一个真实的目录目录,而不是我创建的目录)。由于DC实现INotifyComposablePartCatalogChanged我很困惑,为什么DC没有发现新文件,即使我用新路径创建一个新DC。我得到的变化通知是相关的,但A)与我目前的实现(我刚刚描述),然后改变通知是通过MEF DC和B)实现有什么地方做什么来实现你自己的通知监听器会这样工作吗? – user64718 2010-04-13 13:46:59