Może zdarzyć się, że w używanych dllkach napotkamy na konflikt nazw. Co przez to rozumiem? Więcej niż jedna biblioteka zawiera klasy o identycznej hierarchii klas w przestrzeni nazw. Doskonały scenariusz takiej sytuacji to konieczność wykorzystania kilku wersji tego samego komponentu (swego czasu zetknąłem się z takim czymś używając edytora tekstowego firmy Telerik w kontekście MOSS). Przykład…
1: namespace CommonNamespace 2: { 3: public class ClassWithCommonName 4: { 5: public void FirstDll() 6: { 7: 8: } 9: } 10: }
1: namespace CommonNamespace 2: { 3: public class ClassWithCommonName 4: { 5: public void SecondDll() 6: { 7: 8: } 9: } 10: }
…czyli dwie identycznie nazwane klasy w identycznych przestrzeniach nazw w różnych dllkach różniące się posiadanymi metodami.
Problem można zreprodukować bardzo łatwo, ponieważ przy próbie stworzenia instancji którejś z tych klas kompilator C# rzuci w nas wyjątkiem o treści:
”The type ‘CommonNamespace.ClassWithCommonName’ exists in both ‘[path]\First.dll’ and ‘[path]\Second.dll’”.
Rozwiązaniem jest specjalna konstrukcja w C#, która pozwala nam określić z którego dokładnie pliku ma zostać pobrana klasa o żądanej nazwie. Link do dokumentacji: extern alias na MSDN. Dostanie się do tej funkcjonalności z poziomu Visual Studio nie jest na pierwszy rzut oka widoczne, więc po kolei:
1) dodajemy referencje do bibliotek zawierających klasy o takich samych nazwach zagnieżdżonych w takich samych przestrzeniach nazw:
2) we właściwościach referencji można zauważyć pole Aliases, gdzie domyślną wartość “global” trzeba uzupełnić o własne aliasy, dopisując je po przecinku (mamy tu dowolność):
3) podczas korzystania z którejś ze “skonfliktowanych” klas definiujemy dokładnie jej pochodzenie, posługując się aliasem nadanym wcześniej we właściwościach referencji składnią taką jak poniżej:
I wsio – niby pierdoła, ale dojście do tego potrafi zabrać sporo czasu. Teraz kompilator wie, że ma skorzystać z klasy wkompilowanej w dllkę, do której referencja ma alias “firstDll”.
Mała uwaga dla użytkowników Resharpera: wygląda na to, że Resharper nie rozumie tej konstrukcji i niestety pokazuje błędy tam gdzie ich nie ma. Podobnie ma się sprawa z Intellisense z R# – nie ujrzymy w nim metod zdefiniowanych w klasach pozyskiwanych w ten sposób.