2010-12-14 33 views
10

Mam projekt, który musi odwoływać się do dwóch bibliotek DLL o tej samej nazwie. Biblioteki DLL nie mają silnej nazwy, mają taką samą dokładną nazwę.Używanie dwóch bibliotek DLL o tej samej nazwie i tej samej przestrzeni nazw

Potrzebuję dostępu do niektórych typów w obrębie każdej biblioteki DLL, ale te typy mają taką samą pełną nazwę. Więc powiedzmy DLL1 jest companyDLL.dll -> someProduct.Type1 DLL 2 companyDLL.dll -> someProduct.Type1

Jak mogę uzyskać dostęp zarówno 'Type1' w ramach tego samego projektu?

Próbowałem już używać "zewnętrznego aliasu", ale wymaga to zmiany nazwy jednej z bibliotek DLL.

Proszę dać mi znać, jeśli konieczne jest dalsze wyjaśnienie mojego pytania.

+8

To należy do kategorii "jeśli próbujesz to zrobić, twój projekt jest poważnie uszkodzony." – cdhowie

+0

Zdecydowanie uzgodniono, że jest to narzędzie, które potrzebuje informacji z dwóch wersji produktu firmy (zbudowanego z .NET). Ale produkt, o którym tu mowa, jest regulowany, a zatem nie można go zmienić. – varosh

Odpowiedz

0

Potrafię wymyślić dwa sposoby radzenia sobie z tym.

  1. załaduj każdą bibliotekę DLL do osobnego elementu AppDomain. Będziesz musiał nawiązywać połączenia przez granicę AppDomain, aby łaskotać różne właściwości i metody.

  2. przed załadowaniem złożeń, rozmontowaniem, a następnie ponownym złożeniem każdego zespołu i umieszczeniem ich w unikatowych (być może generowanych dynamicznie) przestrzeniach nazw. Są narzędzia, które mogą pomóc w tym (1) (2). Możesz potencjalnie zautomatyzować to.

Ale moim podstawowym odczuciem jest, że naprawdę nie powinno się tego robić. Łatwiej jest rozwiązać ten problem, niż rozwiązać go po skompilowaniu złożeń.

+0

Cecil może być lepszym rozwiązaniem niż ildazm, ponieważ możesz manipulować IL bezpośrednio za pomocą C#. – cdhowie

+0

Dla # 1 powyżej: jak mogę dodać odniesienie do dwóch bibliotek DLL o tej samej nazwie w tym samym projekcie? – varosh

3

Użycie extern alias do wprowadzenia złożeń z różnymi obszarami nazw. Jeśli możesz rozróżnić przestrzeń nazw, powinieneś być w stanie użyć using altType1 = someProduct.Type1, aby utworzyć lokalny alias dla typu.

pierwsze kwalifikują się zespoły z wiersza poleceń:

/r:ProductA=companyDLLA.dll 
/r:ProductB=companyDLLB.dll 

następnie odwołać je za pomocą extern alias:

extern alias productA; 
extern alias productB; 

Wreszcie można alias lokalnych typów:

using productTypeA = productA.Type1; 
using productTypeB = productB.Type1; 
+0

Niestety dla mnie, dwie biblioteki dll mają tę samą nazwę.i.e./r:ProductA=companyDLLA.dll /r:ProductB=companyDLLA.dll – varosh

+0

czy istnieje powód, dla którego nie można zmienić nazwy biblioteki DLL? Gdybym był w twojej sytuacji, spróbowałbym zmienić nazwy ich "companyDLLv1.dll" i companyDLLv2.dll ". –

+0

Tak, plików DLL nie można zmienić. Dyski DLL, o których tu mowa, są uregulowane i nie można ich zmienić bez przeprowadzenia oficjalnego procesu zatwierdzania (co nie wchodzi w zakres mojego scenariusza). – varosh

11

Jeśli urządzenie dwie biblioteki DLL mają taką samą nazwę, będziesz musiał zmienić ich nazwę. Takich jak Assembly1.dll i Assembly2.dll.

Dodaj te pliki DLL jako odniesienie w projekcie, tak jak zwykle, a we właściwościach dla każdego odwołania określ alias.

w kodzie przy użyciu bibliotek DLL należy użyć extern alias, aby określić, co dll chcesz odwołać.

extern alias Assembly1Reference; 
using Assembly1Reference::AssemblyNamespace.MyClass; 

Jeśli zostawisz to tak, najprawdopodobniej dostać FileNotFoundException mówiąc, że nie można załadować pliku lub zestawu. Aby to naprawić, musisz dodać ResolveEventHandler, który załaduje odpowiedni zestaw, którego próbujesz użyć. Aby to zrobić, musisz dokładnie określić miejsce przechowywania plików DLL.W poniższym przykładzie ręcznie skopiowałem pliki Dll do folderu debugowania projektów. Tam, gdzie jest napisane "nazwa zestawu1", możesz znaleźć nazwę po odwołaniu się do biblioteki DLL, zbudować projekt i otworzyć plik csproj za pomocą notatnika. Czego szukać, będzie poniżej mojego przykładowego kodu.

extern alias Assembly1Reference; 
extern alias Assembly2Reference; 

static void Load() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 
    Do(); 
} 

static void Do() 
{ 
    new Assembly1Reference.Assembly.Class(); 
    new Assembly2Reference.Assembly.Class(); 
} 

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    string currentPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 
    if(args.Name == "Name of assembly1")//Found in csproj file after referenced and built 
    { 
     return System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(currentPath, "Assembly1.dll")); 
    } 
    if(args.Name == "Name of assembly2")//Found in csproj file after referenced and built 
    { 
     return System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(currentPath, "Assembly2.dll")); 
    } 
    return null; 
} 

Zgodnie z obietnicą, oto jak wygląda plik referencyjny w pliku csproj. Nazwa jest wszystkim wewnątrz atrybutu include.

<Reference Include="MyAssembly_3.6.2.0, Version=3.6.2.0, Culture=neutral, PublicKeyToken=12341234asdafs43, processorArchitecture=MSIL"> 
     <SpecificVersion>False</SpecificVersion> 
     <HintPath>Resources\Assembly1.dll</HintPath> 
     <Aliases>Assembly1Reference</Aliases> 
</Reference> 

Wiem, że jest późno, ale mam nadzieję, że pomoże to każdemu, kto wejdzie na tę stronę od teraz.

+0

Jest to użyteczne i mógłbym to zrobić częściowo, ale mam następujące pytania. Jaki jest tego cel? 'static void Do() {new Assembly1Reference.Assembly.Class(); nowy Assembly2Reference.Assembly.Class(); } 'Co to jest zaletą rozwiązania zespołów za pomocą kodu, a nie poprzez app.config jak [this] (https://stackoverflow.com/a/3163050/431561). W moim przypadku zawsze ładuje się najnowsza wersja zestawu. Co należy zrobić, aby załadować dokładną dll określonego zespołu o zmienionej nazwie. – Rajaraman

Powiązane problemy