2009-09-10 13 views
5

Właśnie skończyłem oglądać odcinek Boba Martina w NDC, gdzie powiedział, że "używanie" dyrektyw w języku C# na górze strony jest złe z powodu ścisłego sprzężenia, które tworzą/implikują między komponentami.Alternatywy dla słowa kluczowego "using" w C#?

W jaki sposób można użyć zewnętrznych plików .dll bez dodawania odwołania do projektu i instrukcji użycia?

Pamiętam, jak V6 pozwalało ci stworzyć obiekt przez ciąg ProgId - nie jestem pewien, czy to technika, której szukam, ale jest to przykład języka, który nie potrzebuje projektu odniesienie do użycia biblioteki dll.

EDYCJA: Here is a link to the conference. Przepraszam, nie mam dokładnego cytatu ani minuty w prezentacji, przechodzę pamięcią.

+1

Czy naprawdę tak powiedział, czy też zrozumiałeś to, co powiedział? –

+3

Łącze do tego byłoby pomocne. Chciałbym usłyszeć, co on właściwie powiedział. – tvanfosson

+6

Aby uniknąć nieporozumień, Microsoft nazywa to "dyrektywą". Instrukcja using (słowo kluczowe) zwykle odnosi się do metody użytej w metodach, aby automatycznie wywoływać Dispose na zasoby. – Ash

Odpowiedz

6

To nie jest stwierdzenie, że stosując sam jest zły - to jeśli masz zbyt wiele z nich.

Oświadczenie takie jak using System; rzadko stanowi problem sam w sobie, ale jeśli masz dużo (powiedziałbym więcej niż 3-6, w zależności od tego, które z nich) w tym samym pliku kodu, może to być oznaczenie ścisłe sprzężenie.

Równie dobrze można zastosować podobną zasadę do liczby odniesień w samym projekcie.

Rozwiązaniem sprzężenia zwrotnego jest programowanie na interfejsach i Injection Dependency Injection (DI).

Postępowy sposób robienia rzeczy, które można zapamiętać z VB, był po prostu działaniem COM. Zasadniczo użyłeś tego ProgId, aby uzyskać odwołanie do instancji, która zaimplementowała pożądany interfejs. Minusem było to, że działało to tylko wtedy, gdy obiekt COM był powszechnie zarejestrowany. Pamiętasz piekło dll?

Nadal można zastosować tę samą zasadę przy użyciu określonych smaków DI, tyle że teraz interfejs jest typem .NET i nie jest zdefiniowany w IDL, a do dostarczenia konkretnej implementacji potrzebny jest jakiś kontener DI.

+1

Napisałbym to "to ** może ** być oznaką ścisłego sprzężenia" zamiast "jeśli może być ** wskazaniem ciasnego sprzężenia **" –

+0

@ Vinko Vrsalovic: Nie, nie zgadzam się: Jeśli masz dwadzieścia za pomocą instrukcji, to zdecydowanie * wskazanie * ścisłego sprzężenia. –

+0

Następnie powiedz tak: "to jest ** wskazanie ** ciasnego sprzężenia" –

6

using to skrót do przestrzeni nazw, nie są to odniesienia do plików zewnętrznych. Dlatego to po prostu nie ma sensu.

Niezależnie od tego, co można zrobić, to mieć interfejs DLL (DLL z tylko interfejsami), aby dynamicznie ładować i używać różnych złożeń i tworzyć typy (poprzez odbicie), które można rzutować na dobrze znane interfejsy. Jest to właściwy sposób na rozluźnienie odnośników zewnętrznych przy jednoczesnym zachowaniu korzyści płynących z mocno napisanego języka i wczesnego wiązania.

Zobacz klasy Assembly i AppDomain, aby załadować złożenia, i Activator, aby utworzyć instancje typu według nazwy.

+6

Uzgodnione. Ten facet, który mówi, że "używanie" stwierdzeń jest złe, wyraźnie nie wie, o czym mówi. – Noldorin

+4

@Noldorin: Robert C. Martin nie wie, o czym mówi ?! –

+1

Albo został źle zrozumiany. Kto był lub jest zły, nie ma większego znaczenia, ponieważ "otrzymana wiadomość" nie ma sensu. – Lucero

7

Uważam, że Bob Martin odnosi się do wczesnego i późnego wiązania.

W późnym wiązaniu .NET możliwe jest odzwierciedlenie, a dokładniej klasa Activator, która umożliwia utworzenie typu w zewnętrznym zestawie przy użyciu nazwy pliku lub nazwy zespołu.

Zwykle używanie dyrektyw (a nie instrukcji using) idzie w parze z bezpośrednim odwoływaniem się do zewnętrznego zespołu. to znaczy. Dodaje się odwołanie do złożenia, a następnie dodaje się za pomocą dyrektyw, aby uniknąć konieczności wpisywania hierarchii pełnego obszaru nazw podczas korzystania z typów zewnętrznych.

Jeśli więc twój kod zawiera dużą liczbę dyrektyw u góry, możliwe jest, że odwołujesz się do wielu innych typów bezpośrednio, zwiększając zależność/zależność twojego kodu na tych typach.

Przypuszczam, że właśnie dlatego Bob określa je jako złe. Odpowiedź na pytanie "czy to naprawdę jest złe?" jest bardzo subiektywny i zależny od kontekstu.

Ogólnie rzecz biorąc, de-sprzężenie komponentów jest prawie zawsze dobrym celem do osiągnięcia w projektowaniu oprogramowania. Dzieje się tak dlatego, że pozwala na zmianę części systemu przy minimalnym wpływie na resztę systemu. Po przeczytaniu jednej lub dwóch książek Boba Martina, spodziewałbym się, że właśnie to osiąga.

1

Możesz zrobić to, o czym mówisz poprzez odbicie. Możesz załadować zespół w czasie wykonywania i przejrzeć go, aby uzyskać klasy itp. I wywoływać je dynamicznie.

Osobiście nie zrobiłbym tego, aby uniknąć sprzężenia. Według mnie jest to złe użycie refleksji i wolałbym raczej dodać ją do projektu i powołać się na nią, chyba że istnieje konkretny powód, dla którego nie należy tego robić. Odbicie dodaje do systemu ponad głową, a ty nie czerpiesz korzyści z czasu kompilacji.

+0

Co więcej, ta "technika" * nie * uniknie sprzężenia. Twój kod nie jest mniej sprzężony z zewnętrzną biblioteką DLL, ponieważ wywołujesz ją dynamicznie - jeśli nie ma tam biblioteki DLL, twój kod nie będzie działał. – MusiGenesis

+1

Zmniejsza sprzężenie, jeśli masz zespół interfejsu i dynamicznie ładuje obiekty, które mają interfejsy. Wstrzyknięcie zaleŜności jest równieŜ dobrym podejściem. – kenny

+0

@Kenny: w tym przypadku masz całkowitą rację. Stwierdziłem, że jeśli usuniesz odwołanie i zamiast tego załadujesz je dynamicznie, nie poprawisz sytuacji. – MusiGenesis

2

Można użyć refleksji:

// Load the assembly 
Assembly assembly = Assembly.LoadFrom(@"c:\path\Tools.dll"); 
// Select a type 
Type type = assembly.GetType("Tools.Utility"); 
// invoke a method on this type 
type.InvokeMember("SomeMethod", BindingFlags.Static, null, null, new object[0]); 
+4

Ten typ wywoływania nazywa się późnym wiązaniem i jest nie tylko powolny i podatny na błędy, ale także dość kłopotliwy w językach takich jak C#, które nie są zaprojektowane do wspierania późnego wiązania z pudełka (na przykład przez magię kompilatora). Jeśli to możliwe, unikałbym tego podejścia. – Lucero

+0

Lepiej używać ramek DI dla tego rodzaju rzeczy, szczerze. Lepiej także dla nieobszarowitych. – Will

Powiązane problemy