2013-04-22 18 views
10

Wydanie aktualizacji wtyczki MEF Runtime Wydanie

Numer

Mój kod MEF nie aktualizuje prawidłowo złożeń w czasie wykonywania, z folderu powiązanego z katalogiem katalogowym. Wtyczki ładują się w czasie wykonywania, ale gdy zaktualizuję bibliotekę DLL i wywołasz Refresh w katalogu DirectoryCatalog, złoŜenia nie są aktualizowane.

Tło

buduję dll, który ma MEF pojemnik i wykorzystuje DirectoryCatalog znaleźć folder wtyczek lokalnej. Obecnie nazywam tę bibliotekę dll z prostego WinForm, czyli z osobnym projektem do używania ShadowCopy, dzięki czemu mogę nadpisać biblioteki DLL w folderze wtyczek. Zamiast korzystać z FileWatchera w celu aktualizacji tego folderu, ujawniam publiczną metodę, która wywołuje odświeżenie w DirectoryCatalog, więc mogę aktualizować zestawy bez zmian, automatycznie.

Kod

klasa bazowa instancję katalogi MEF i pojemnik, i zapisuje je jako zmienne klasy dostęp do referencyjnego później

public class FieldProcessor 
{ 
    private CompositionContainer _container; 
    private DirectoryCatalog dirCatalog; 

    public FieldProcessor() 
    { 
     var catalog = new AggregateCatalog(); 
     //Adds all the parts found in the same assembly as the TestPlugin class 
     catalog.Catalogs.Add(new AssemblyCatalog(typeof(TestPlugin).Assembly)); 
     dirCatalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory + "Plugin\\"); 
     catalog.Catalogs.Add(dirCatalog); 

     //Create the CompositionContainer with the parts in the catalog 
     _container = new CompositionContainer(catalog); 
    } 

    public void refreshCatalog() 
    { 
     dirCatalog.Refresh(); 
    } 

} ... 

oto plugin próbuję zastąpić. Mój test aktualizacji polega na tym, że zwrócone żądła są wyprowadzane do pola tekstowego, zmieniam ciągi znaków, które wtyczka powraca, przebudowuje i kopiuje do folderu wtyczek. Ale nie aktualizuje się dla uruchomionej aplikacji, dopóki nie zamknę i nie uruchomię ponownie aplikacji.

[Export(typeof(IPlugin))] 
[ExportMetadata("PluginName", "TestPlugin2")] 
public class TestPlugin2 : IPlugin 
{ 
    public IEnumerable<IField> GetFields(ContextObject contextObject, params string[] parameters) 
    { 
     List<IField> retList = new List<IField>(); 
     //Do Work Return Wrok Results 
     retList.Add(new Field("plugin.TestPlugin2", "TestPluginReturnValue2")); 
     return retList; 
    } 
} 

Edit

komunikat importu

[ImportMany(AllowRecomposition=true)] 
    IEnumerable<Lazy<IPlugin, IPluginData>> plugins; 

Badania

zrobiłem dość szeroko zakrojone badania i wszędzie w artykułach i próbki kodu odpowiedź wydaje się, aby dodać DirectoryCatalog do pojemnika i zapisać odwołanie do tego katalogu, a następnie wywołanie Refresh w tym odwołaniu, po dodaniu nowej wtyczki, a ona zaktualizuje zestawy ... co robię, ale nie pokazuje zaktualizowanych danych wyjściowych z nowej biblioteki DLL wtyczki.

Żądanie

Czy ktoś widział ten problem, czy też wiesz, co może powodować moje problemy z niezmontowaniem złożeń w czasie wykonywania? Wszelkie dodatkowe informacje lub wglądy zostałyby docenione.

Rozdzielczość

Dzięki Panos i Stumpy za ich linki, które doprowadziły mnie do rozwiązania mojego problemu. Dla przyszłych poszukiwaczy wiedzy, moim głównym problemem było to, że metoda Refresh nie aktualizuje zespołów, gdy nowy zestaw ma dokładnie taką samą nazwę zestawu, jak nadpisana biblioteka dll. Dla mojego POC właśnie przetestowałem przebudowę z datą dołączoną do nazwy zespołu i wszystkim innym tym samym, i to działało jak wdzięk. ich linki w komentarzach poniżej były bardzo przydatne i są zalecane, jeśli masz ten sam problem.

+1

DirectoryCatalog.Refresh będzie nie wykrywa zaktualizowanych assebmlies. Tylko nowe lub usunięte. Rzuć okiem na tę odpowiedź dla obejścia i sugestie: http://stackoverflow.com/a/14842417/850119 –

+0

Moje biblioteki DLL są zablokowane, gdy są one ładowane, więc nie mogę zastąpić je nowymi bibliotekami dll. Czy nie masz tego problemu? czy zrobiłeś coś, co uczyniło je aktualizowalnym. –

+0

Tak, miałem ten problem. Jednym z kroków, o których wspomniałem, było "Włączenie kopiowania". Shadow Copy umożliwia programowi pobieranie lokalnych kopii bibliotek dll i dodawanie ich do lokalnej pamięci podręcznej, zamiast blokowania bibliotek dll. To musi być włączone, aby umożliwić ci "hot swap" biblioteki DLL podczas wykonywania, w przeciwnym razie musisz zatrzymać program, zmienić biblioteki DLL, a następnie uruchom go ponownie. Myślę, że jest to przykład, na który patrzyłem, ale jeśli to nie działa, to google MEF i Shadow Copy, http://stackoverflow.com/questions/12593308/mef-and-shadowcopying-dlls-so-that-i -can-overwrite-them-at-runtime – Madullah

Odpowiedz

3

czy ustawiłeś parametr AllowRecomposition na atrybut importu?

AllowRecomposition 
Gets or sets a value that indicates whether the property or field will be recomposed when exports with a matching contract have changed in the container. 

http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importattribute(v=vs.95).aspx

edit:

DirectoryCatalog nie aktualizuje tylko zespoły, dodane lub usunięte: http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.directorycatalog.refresh.aspx

do pracy w okolicy: https://stackoverflow.com/a/14842417/2215320

+0

Zrobiłem, przykro mi, że nie napisałem oryginalnie kodu oryginalnego, zaktualizowałem pytanie, aby odzwierciedlić moją deklarację importu. – Madullah

+0

i Twój kod odświeżania? Myślę, że problem tkwi w środku. Powiedziałeś, że nie używasz FileSystemWatcher, w jaki sposób wykrywasz i ponownie ładujesz swoje złożenia? – Niels

+0

Ujawniam to za pomocą metody RefreshCatalog widzianej powyżej. Wywołuję tę metodę z zdarzenia click button na winForm. – Madullah