2013-11-26 17 views
10

Mam dwa zespoły: App i AddOn. App - referencje AddOn, ale CopyLocal jest ustawione na false, ponieważ AddOn będzie ładowane dynamicznie przez App.Dlaczego potrzebuję obsługi AssemblyResolve dla zespołu, który jest już załadowany?

Oto kod w AddOn:

namespace AddOn 
{ 
    public class AddOnClass 
    { 
     public static void DoAddOnStuff() 
     { 
      Console.WriteLine("AddOn is doing stuff."); 
     } 
    } 
} 

i oto kod w App:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Assembly.LoadFrom(@"..\..\..\AddOn\bin\Debug\AddOn.dll"); 

     // Without this event handler, we get a FileNotFoundException. 
     // AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => 
     // { 
     //  return AppDomain.CurrentDomain.GetAssemblies() 
     //      .FirstOrDefault(a => a.FullName == e.Name); 
     //}; 

     CallAddOn(); 
    } 

    [MethodImpl(MethodImplOptions.NoInlining)] 
    private static void CallAddOn() 
    { 
     AddOnClass.DoAddOnStuff(); 
    } 
} 

Co ja nie rozumiem, dlaczego kod nie działa z AssemblyResolve przewodnik skomentował w Main(). Po uruchomieniu w Visual Studio debuger łamie się na CallAddOn() za pomocą . Dlaczego narzeka? Zespół jest ładowany i jest to dokładnie ta sama wersja (to jest ten sam plik na dysku), co zostało wymienione w App.

Mam wrażenie, że istnieje pewne podstawowe pojęcie, którego tutaj nie rozumiem. Komentarz z obsługą AssemblyResolve działa dobrze, ale wygląda na to, że jest hackerem i nie rozumiem, dlaczego go potrzebuję, ponieważ wygląda na to, że robi coś trywialnego.

+1

Robisz to źle. Kiedy zezwalasz na używanie dodatków w swoim programie, * nie wiesz * typu klasy w dodatku. Został napisany przez innego programistę. Więc powinieneś być bardzo zainteresowany wartością zwracaną przez LoadFrom(), na przykład użyjesz Assembly.GetType(), aby odkryć typ. –

+0

Jest to dodatek, który odwołuje się do innego dodatku, ponieważ polega na tej funkcji. – RobSiklos

+0

To nie jest dodatek, tylko normalny zestaw zależny. Zawsze używasz opcji Kopiuj lokalne = Prawda, aby zapewnić, że narzędzie CLR może znaleźć zestaw automatycznie, bez konieczności pomocy. Jakie jest ustawienie domyślne. –

Odpowiedz

9

Powodem jest to, że istnieje wiele kontekstów ładowania złożenia. Kontekst, w którym jest ładowany zestaw, wpływa na sposób jego użycia. Gdy zestaw jest ładowany przez środowisko wykonawcze przy użyciu domyślnego mechanizmu próbkowania, jest on umieszczany w tak zwanym kontekście ładowania. Jest to kontekst używany podczas ładowania zespołu przez Assembly.Load. Załadowałeś zespół przy użyciu LoadFrom, który używa własnego kontekstu. Sondowanie nie bada kontekstu LoadFrom, a plik nie znajduje się na ścieżce próbkowania, więc musisz go rozwiązać w środowisku wykonawczym. To jednak nie jest symetryczne. Jeśli zestaw zostanie załadowany w kontekście Wczytaj, najpierw pobierze go stamtąd (zakładając, że tożsamość jest taka sama dla niepodpisanych złożeń, ścieżka jest częścią tożsamości). Zaznaczę, że jest więcej kontekstów, w tym ReflectionOnlyLoad i ReflectionOnlyLoadFrom. LoadFile ładuje zespół bez kontekstu, tj. Wszystkie zależności należy załadować ręcznie.

Jeśli chcesz, aby złoŜenia były rozwiązywane w kontekście Load, ale istnieją poza domyślną ścieżką sondowania aplikacji, moŜesz to zrobić równieŜ poprzez konfigurację. Użyj elementu <codebase> przekierowania wiązania zespołu lub atrybutu privatePath elementu <probing>.

Przeczytaj this, aby uzyskać więcej informacji. Istnieją również posty na blogu autorstwa Suzanne Cook od jakiegoś czasu na temat ładowania zespołów i kontekstów (patrz here, here i here).

Powiązane problemy