2012-09-26 17 views
11

Próbuję zatrzymać pliki DLL blokujące aplikacje w katalogu wtyczek MEF, dzięki czemu mogę nadpisać złożenia w czasie wykonywania (uwaga: Nie próbuję ponownie załadować MEF ich w locie, przy następnym uruchomieniu aplikacji jest w porządku, po prostu nie chcę, aby zatrzymać aplikację, aby zrobić kopię)Pliki DLL MEF i ShadowCopying, dzięki czemu mogę je zastąpić w czasie wykonywania

Próbuję to zrobić, tworząc domenę app skopiowane cień dla moich załadowanych zespołów mef poniżej:

[Serializable] 
    public class Composer:IComposer 
    { 
     private readonly string _pluginPath; 
     public Composer(IConfigurePluginDirectory pluginDirectoryConfig) 
     { 
      _pluginPath = pluginDirectoryConfig.Path; 
      var setup = new AppDomainSetup(); 
      setup.ShadowCopyFiles = "true"; // really??? is bool not good enough for you? 
      var appDomain = AppDomain.CreateDomain(AppDomain.CurrentDomain.FriendlyName + "_PluginDomain", AppDomain.CurrentDomain.Evidence, setup); 

      appDomain.DoCallBack(new CrossAppDomainDelegate(DoWorkInShadowCopiedDomain));  
     } 

     private void DoWorkInShadowCopiedDomain() 
     { 
      // This work will happen in the shadow copied AppDomain. 

      var catalog = new AggregateCatalog(); 
      var dc = new DirectoryCatalog(_pluginPath); 
      catalog.Catalogs.Add(dc); 
      Container = new CompositionContainer(catalog); 
     } 

     public CompositionContainer Container { get; private set; } 
    } 

a następnie dostęp do katalogu komponentów MEF za pośrednictwem CompositionContainer na tej klasie. Jednak wydaje się, że kontener kompozycji jest inicjowany tylko wewnątrz domeny shadowcopy (co ma sens), a to oznacza, że ​​jest ona pusta w mojej domenie aplikacji. Właśnie zastanawiałem się, czy istnieje lepszy sposób to zrobić lub jakiś sposób do zapytania domeny, aby uzyskać moje składniki MEF

+2

Wygląda na to, że można po prostu wywołać File.Copy na wszystkich plikach w katalogu wtyczek, używając własnego ręcznie utworzonego katalogu shadow. Następnie wystarczy załadować ze ścieżki cienia w głównej domenie. –

+0

Zastanowiłem się nad tym, ale rozumiem, że jest to problem, który ma rozwiązać kopiowanie w tle (dlatego prawdopodobnie mają do czynienia z bardziej ograniczonymi przypadkami). Czy wiesz, że shadowcopying jest większy niż to, czy robi kopię ręcznie wystarczająco dobrze? –

+0

@DanBryant na podstawie odpowiedzi Czuję, że jest to najlepsze rozwiązanie dla nas, jeśli umieścisz to jako odpowiedź przed końcem nagrody, nagrodzę cię nagrodą. –

Odpowiedz

-2

Czy masz opcję nie używać DirectoryCatalog i używać AssemblyCatalog, aby załadować wszystkie złożeń w katalogu ? Można nawet przejść do kodu plex i skopiować ten sam kod z klasy DirectoryCatalog, która czyta przez katalog i ładuje do góry złożenia.

Utracisz możliwość załadowania ich w locie, ale jak już wspomniałeś, to naprawdę nie jest wymagane.

+0

Hey @zync Być może brakuje mi tego, co masz na myśli, ale jak mogę obejść problem z kopią w tle/krzyżową domeną aplikacji przez wdrożenie mojej własnej DirecoryCatalog. Czy istnieje sposób, aby powiedzieć, aby pobierać z oddzielnej domeny aplikacji? może mógłbyś dodać kilka dodatkowych informacji o tym, co masz na myśli –

+0

@LukeMcGregor - moja sugestia nie zadziała. Ale robiłem trochę dookoła, a to nie jest kwestia MEF. Domena aplikacji blokuje wszystkie dotknięte zespoły. http://stackoverflow.com/questions/2745093/overwriting-dlls-in-mef –

+0

Tak, masz rację, moim problemem nie jest konkretnie problem MEF, ale bardziej problem z kopią w tle/appdomain. –

-1

Ten scenariusz jest bliższy funkcji automatycznej aktualizacji w aplikacjach mobilnych. Zasadniczo chcesz wybrać nowe złożenia, jeśli są dostępne w aplikacji Start/Restart.

Jednym ze sposobów zaprojektowania tego może być mechanizm komunikacyjny do sygnalizowania początkowej dostępności nowych złożeń (być może plik version.txt). Jeśli tak, to ten sam plik version.txt może wskazywać na nową lokalizację złożeń. Tak - może się zdarzyć, że utworzysz kilka podkatalogów wskazujących właściwą wersję, ale mogą one zostać wyczyszczone przez inny proces.

można użyć struktury hierarchichal jak tak -

Version \ - version1.0 \ - Version2.0 \

Ten typ konstrukcji byłoby bliżej do paradygmatu aktualizacji auto dobrze znają .

+0

dodajemy to jako nową odpowiedź, ponieważ jest to inne podejście do rozwiązania ogólnego problemu niż konkretny problem. –

+0

Myślę, że podejście, które sugerujesz, jest takie samo jak wcześniejsze sugestie Dana Bryanta, aby ręcznie wykonać tę samą funkcję co kopiowanie w tle. Czuję się trochę hacky robiąc to, ponieważ zasadniczo klonuje istniejącą funkcję .NET. Po prostu chcę się upewnić, zanim zrobię to, że nie ma dobrego sposobu na uzyskanie dostępu do domeny krzyżowej. –

3

Jeśli nie chcesz stosować rozwiązania Dan Bryant i zync, możesz utworzyć aplikację powłoki, która po prostu wykonuje twoją aplikację w nowym AppDomain.

podejście byłoby:

  1. Utwórz nowy projekt aplikacji, która będzie zastosowanie powłoki.
  2. W aplikacji powłoki utwórz AppDomain, włącz kopiowanie w tle, a jeśli chcesz, określ katalog, w którym włączone będzie kopiowanie w tle.
  3. Użyj AppDomain.ExecuteAssembly, aby zadzwonić do bieżącej aplikacji.

Jeśli zamiast aplikacji masz biblioteki klas można spróbować następujących czynności:

  1. utworzyć nowy projekt biblioteki klas.
  2. Dodaj następujący interfejs do nowego projektu biblioteki klasy:

    public interface IRemoteLoader 
    { 
        void Load(); 
        void Unload(); 
    } 
    
  3. Dodaj implementację tego interfejsu do swojej biblioteki klas, które musi wykonać w nowym AppDomain. W metodach Load i Unload należy dodać kod, aby wykonać odpowiednio inicjowanie i czyszczenie. Ustaw klasę na MarshalByRefObject. Jest to potrzebne do .NET Remoting do tworzenia obiektów proxy na obu domenach aplikacji.

  4. Po utworzeniu nowego AppDomain, użyj CreateInstanceAndUnwrap aby utworzyć instancję klasy ładowarka od kroku 3.

  5. Użyj Load i Unload na obiekcie stworzonym od kroku 4.

Będzie to wystarczające, jeśli nie będziesz precyzyjnie kontrolować i wystarczy tylko uruchomić/zatrzymać.

+0

@panosrontogainnis tak Zgadzam się, że to wydaje się być najbardziej obsługiwanym sposobem rozwiązania problemu (np. Bootstrap/shadowcopy całej aplikacji.niestety w moim przypadku nie kontroluję bootstrap (tak jak w NServiceBus.Hosted), więc to rozwiązanie Powiedziawszy, że uważam, że jest to prawdopodobnie najlepsze rozwiązanie dla innych, –

+0

Pozdrawiam. Dodałem inne podejście, które działa z bibliotekami klas. –

Powiązane problemy