2009-07-27 20 views
6

Próbowałem złamać tę wersję w ciągu ostatnich kilku tygodni i nie znalazłem jeszcze dobrego rozwiązania; mam nadzieję, że mogę tu znaleźć odpowiedź.Ładowanie 2 wersji zestawu w czasie wykonywania

Mam dwa zespoły (ZA & ZB), z których oba wskazują na wspólny projekt/dll (ZC), ale które mogą być w innej wersji (tj. Ta sama nazwa dll, te same przestrzenie nazw, niektóre klasy mogą być różne) . Każdy zestaw działa sam, jednak jeśli jeden jest ładowany przez inny w czasie wykonywania (np. A ładuje B), to nie mogę go uruchomić. Potrzebuję pomocy.

Oto konfiguracja:

  • ZA zależy ZC (wspólne) w wersji 1.1
  • ZB zależy od wersji ZC 1,0

ZA musi załadować potrzeby załadować coś w ZB (co zależy od ZC), w czasie wykonywania.

ZA to aplikacja główna. W katalogu bin znajduje się katalog wtyczek plugins/plugin-ZB, pod którym chciałbym umieścić wszystkie ZB i jego zależności (ZC).

Oto, co starałem dotąd:

Assembly.Load() użyciu tej samej wersji dll - pracował w porządku.

Assembly.Load() stosując różne wersje dll - ZB obciążeń, ale gdy metoda działa, mam metodę nie znaleziono wyjątku.

AppDomain.Load() Błąd pliku nie znaleziono błąd; Skorzystałem nawet z delegata, aby rozwiązać zjazdy.

Niektóre szczegóły dotyczące ZC: - niektóre metody są publiczne statyczny (niektóre nie są). Na przykład. Log.Log("hello"); - niektóre mogą zwracać wartości (prymitywy lub obiekty). - niektóre metody nie są statyczne (i wartości zwracane).

Pomoc? - TIA

Odpowiedz

1

Oprócz Jonathan Allen doskonałą radę, bardziej „klasyczny” sposób na rozwiązanie tego problemu jest przez załadowanie wersji 2 w 2 różnych AppDomanis. Następnie można użyć programu .NET Remoting, aby komunikować się dwie aplikacje AppDomains. Więc ZA powinien utworzyć nowe Appdomain, załadować w tym AppDomain ZB i wywołać pewną operację w ZB poprzez Remoting.

Należy zauważyć, że .NET Remoting ma pewne wymagania dotyczące klas, które mają być używane (dziedziczenie z MarshalByRef), a tworzenie AppDomain jest kosztowną operacją.

Nadzieja ta pomoc

+0

„Można mieć tylko jedną wersję zespołu o wydanie AppDomain” nie jest prawdą. Możliwe jest nawet odwołanie się do dwóch wersji zespołu z jednego zespołu, wyszukanie zewnętrznego aliasu po więcej informacji, oto pierwsza rzecz, która pojawia się w Google na przykładzie funkcji: http://blogs.msdn.com/ b/ansonh/archive/2006/09/28/extern-alias-walkthrough.aspx – Graham

+0

Używanie dwóch AppDomains jest rozwiązaniem opisanego problemu. – Graham

+0

Masz rację, odpowiedź zaktualizowana! –

0

miałem dwie wersje tego samego zespołu załadowanego w tym samym czasie. Stało się tak ze scenariuszem tak, jak go opisałeś.

Musisz przekonać środowisko wykonawcze, aby załadować tę samą wersję ZC dla ZA i ZB. Znalazłem dwa sposoby, aby to zrobić:

  1. Użyj elementu bindingRedirect w pliku App.config. Jest kilka szczegółów w this question.
  2. Użyj wydarzenia AppDomain.AssemblyResolve. Istnieją pewne szczegóły w this answer.

Jedynym problemem z AppDomain.AssemblyResolve jest to, że wyzwala się tylko wtedy, gdy środowisko wykonawcze nie może znaleźć żądanej wersji. Jeśli obie wersje są dostępne, musisz użyć narzędzia bindingRedirect. Użyłem zdarzenia AppDomain.AssemblyResolve, a następnie dodałem sprawdzenie bezpieczeństwa, które upewnia się, że została załadowana właściwa wersja, przeglądając zgromadzoną kolekcję złożonych kolekcji. Jeśli tak nie jest, narzekam użytkownikowi, że stara wersja biblioteki leży i mówi im, gdzie jest.

+1

Nie ładuje się dwóch różnych wersji, ładuje tę samą wersję dwa razy. –

+1

Kiedy miałem ten problem, @Cameron, podczas uruchamiania uruchomiono wersję 1.1 ZC. Następnie, gdy załadowałem wtyczkę ZB, w czasie pracy załadowano wersję 1.0 ZC. To mam na myśli, ładując dwie różne wersje. Aby ZA i ZB przekazywały sobie wzajemnie obiekty z ZC, musiałem sprawić, aby oba ładowały tę samą wersję ZC. Właśnie to opisuję w mojej odpowiedzi. Czy źle zrozumiałem pierwotne pytanie? –

3
m_Assembly1 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "Old Version\Some.dll")) 
    m_Assembly2 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "New Version\Some.dll")) 

    Console.WriteLine("Old Version: " & m_Assembly1.GetName.Version.ToString) 
    Console.WriteLine("New Version: " & m_Assembly2.GetName.Version.ToString) 

    m_OldObject = m_Assembly1.CreateInstance("FullClassName") 
    m_NewObject = m_Assembly2.CreateInstance("FullClassName") 

Odtąd użyłem późnego wiązania i/lub odbicia, aby przeprowadzić testy.

.NET: Load two version of the same DLL

+0

Doskonała porada! tego nie wiedziałem –

Powiązane problemy