我在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