2009-10-20 18 views
14

Powiedzmy, że mamy aplikację, która składa się z jednego pliku wykonywalnego i 5 bibliotek. Regularnie wszystkie z nich będą zawarte w jednym katalogu, a biblioteki będą tam ładowane.C#: Custom assembly directory

Czy jest to możliwe, że mogę mieć na przykład niektóre z bibliotek w jednym katalogu o nazwie Lib, a reszta w jednym o nazwie Lib2? Aby katalog aplikacji zawierał tylko plik wykonywalny, a pozostałe zespoły byłyby zawarte w różnych katalogach logicznych.

Jak mogę to zrobić? I chciałbym wiedzieć, jak wykonać ładowanie złożeń, ale także jak sprawić, aby budowanie aplikacji umieściło złoŜenia w odpowiednim katalogu.

+0

Tak, można, za odpowiedź DotNetWill użytkownika. Ale niewiele można zyskać i możesz napotkać wiele problemów związanych z konserwacją. –

Odpowiedz

30

Możesz dodać dodatkowe ścieżki wyszukiwania do pliku app.config, aby załadować złożenia. Na przykład:

<runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
    <probing privatePath="lib;thirdParty" /> 
    </assemblyBinding> 
</runtime> 

Możesz zobaczyć więcej szczegółów here.

+0

Fantastyczne. Jeśli chciałbyś mieć więcej ścieżek, czy dodałbyś inny tag '', czy też dodałbyś inne '' z innym znacznikiem ''? – Svish

+0

Czy istnieje również sposób dodania tej ścieżki w czasie wykonywania? Na przykład, jeśli został zbudowany przy użyciu niektórych zmiennych środowiskowych lub innych rzeczy. – Svish

+0

@ Svish # 2: Zobacz moją odpowiedź. – SLaks

2

Aby automatycznie skopiować złożenia do folderu, w którym mają się znajdować, można ustawić wartość Copy Local na wartość true dla wszystkich odniesień i wykonać krok po instalacji, aby przenieść je do podkatalogów.

Alternatywnie, można ustawić Copy Local false i dodać odpowiednie pliki DLL jako pliki w projekcie w odpowiednich podkatalogów, a ustawione Build Action skopiować do katalogu wyjściowego (Pozwoli to zachować podkatalogów)

Najbardziej elastyczny sposobem na znalezienie ich w środowisku wykonawczym jest obsłużenie zdarzenia AppDomain.AssemblyResolve i ręczne załadowanie zespołu przy użyciu Assembly.LoadFile. Będziesz potrzebował jakiś sposób, aby twój kod wiedział, które zespoły są w jakich katalogach.

+0

To, co AssemblyResolve mogłoby być naprawdę bardzo pomocne. Tak naprawdę nie wiedziałem o tym. Co do powiedzenia na temat rzeczy budujących to najczystsze rozwiązanie? Wydaje mi się, że obaj wydają się trochę nieporządni, ale tak naprawdę nie próbowałem żadnego z nich, więc nie mam pojęcia: p – Svish

+0

Jeśli używasz odwołań do środowiska wykonawczego, to skopiuj je do lokalnej wersji, nie pomogłyby. np. jeśli korzystasz z interfejsu, moduły wtyczek są dostępne tylko w czasie wykonywania, a odniesienia do czasu projektowania nie będą działały w tym kontekście. – Krishna

0

W swoim komentarzu wspomniałeś o dodawaniu ścieżek i lokalizacji w czasie wykonywania. Tak, możesz, ale musisz użyć Assembly.Load() i być może refleksji.

11

Jeśli chcesz ręcznie zarządzać gdzie montuje się z, masz dwie możliwości:

  1. obsłużyć zdarzenia AppDomain.AssemblyResolve (jak to zostało opisane przez SLaks). Oto fragment kodu:

    static void Main(string[] args) 
    { 
        ... 
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 
        ... 
    } 
    
    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
        string assembliesDir = "your_directory"; 
        Assembly asm = Assembly.LoadFrom(Path.Combine(assembliesDir, args.Name + ".dll")); 
        return asm; 
    } 
    
  2. Tworzenie domeny z własnymi ustawieniami (poprzez ustawienie ApplicationBase lub PrivateBinPath właściwości obiektu AppDomainSetup).

Więc jeśli chcesz nadal pracować w bieżącej domenie trzeba użyć metody 1.

+0

dziękuję! właśnie mnie uratowałeś, szukałeś takiego rozwiązania, ale nie znalazłeś odpowiedzi na inne pytania. To sprawiło, że mój dzień :) – SwissCoder

+0

Próbuję załadować zespół przy użyciu Assembly.Load, który nie jest w GAC, który nie powiedzie się i zdarzenia AssemblyResolve zostanie uruchomiony, gdzie używam LoadFrom, aby załadować go ze ścieżki. Teraz ten zestaw zostanie załadowany w kontekście ładowania, więc czy teraz używa teraz Ngen 'ed obrazów? dzięki za pomoc – paritosh