Kiedy używasz odbicia? Wzory / anty-wzory

Rozumiem API reflection (w c#) ale nie jestem pewien w jakiej sytuacji bym go użył. Jakie są niektóre wzory-anty-wzory do korzystania z odbicia?

Author: George Stocker, 2009-01-10

17 answers

Jedynym miejscem, w którym użyłem Reflection stuff w C#, były wzorce fabryczne, gdzie tworzę obiekty (w moim przypadku słuchacze sieciowe) na podstawie informacji o pliku konfiguracyjnym. Plik konfiguracyjny zawierał lokalizację złożeń, nazwę typów w nich zawartych oraz wszelkie dodatkowe potrzebne argumenty. Fabryka podniosła to i na tej podstawie stworzyła słuchaczy.

 25
Author: Harper Shelby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:27:50

W jednym produkcie, nad którym pracuję, często go używamy, ale odbicie to złożona, powolna bestia. Nie szukaj miejsc, w których można go używać tylko dlatego, że brzmi zabawnie lub interesująco. Będziesz go używać, gdy napotkasz problem, którego nie można rozwiązać w żaden inny sposób (dynamiczne ładowanie zespołów dla wtyczek lub RAM, Kontrola montażu, fabryki, w których typy nie są znane przy kompilacji, itp.). Z pewnością warto zajrzeć do samouczków reflection, aby zobaczyć, jak to działa, ale nie wpadnij w pułapkę "mając młotek i wszystko, co wygląda jak gwóźdź."Ma bardzo wyspecjalizowane przypadki użycia.

 32
Author: ctacke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-01 13:17:57

Nie wiem, czy jest to wzorzec, ale używam reflection do generowania SQL z definicji klas DAO.

 11
Author: Otávio Décio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:27:18

Nie ma twardych i szybkich reguł. Zasadniczo nie używa się odbicia bez ważnego powodu. Używaj reflection, gdy nie możesz bez niej zrobić tego, co chcesz, lub gdy twój kod byłby znacznie dłuższy lub trudniejszy do zrozumienia bez refleksji.

 8
Author: Andru Luvisi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:27:23

Użyłem refleksji w wielu miejscach. Główne szerokie kategorie obejmują:

  1. automatycznie wygenerowany GUI (czyli Edytor właściwości). Możesz zapętlić właściwości obiektu i użyć rejestru fabryk elementów interfejsu użytkownika do zbudowania formularza. Używam atrybutów na właściwościach, aby kierować tworzeniem interfejsu użytkownika.
  2. serializacja. Napisałem frameworki serializacji, które wykorzystują odbicie do serializacji i deserializacji obiektów.
  3. Usługi Internetowe. Podobnie jak serializacja, używałem reflection do tworzenia i konsumowania komunikatów SOAP, a także do generowania WSDL.
  4. Języki Specyficzne Dla Domeny . Zinterpretowane języki skryptowe zazwyczaj wiążą się z obiektami i metodami wykorzystującymi reflection.
  5. narzędzia debugowania . Takie narzędzia mogą używać refleksji do badania stanu obiektu. Przydatne do tworzenia komunikatów dziennika w Warunkach awarii.

Patterns wise, I ' m not sure what the patterns are. Często wątek pomiędzy wszystkimi zastosowaniami to reference by name I late binding - chcesz powiązać z członkiem w czasie wykonywania. Dzieje się tak często, gdy dynamicznie ładujesz zespoły i nie znasz typów obiektów, które musisz utworzyć/manipulować.

Używanie reflection jest potężne, ale nie sprawi, że będziesz bardziej popularny na imprezach. Używaj go tylko wtedy, gdy sprzęgło jest celowo słabe. Tak słaby, że spodziewasz się, że pęknie w czasie wykonywania. Doskonałym przykładem jest powiązanie danych w WPF.

Nie jestem pewien anty-wzorce, ale z pewnością odnosiłoby się to do robienia rzeczy w czasie wykonywania, które powinny być wykonane w czasie kompilacji...

 8
Author: Daniel Paull,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-10 01:09:02

Uważam, że refleksja (połączona z ładowaniem klasy runtime) jest niezbędna do implementacji pluginów:

  1. Szukaj słoików / zespołów w znanym miejscu
  2. wylicz Jary / zespoły dla klas obsługujących interfejs, który obsługuje twoja wtyczka
  3. Tworzenie instancji wtyczki w czasie wykonywania
 6
Author: JeffV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:49:38

Nie zamierzam rzucać żadnych wzorów, ale sugerowałbym, że dobrym pomysłem jest unikanie refleksji, dopóki nie będzie to potrzebne. Jest to szczególnie przydatne w sytuacjach interop i rozszerzalności, w których nie można kontrolować z wyprzedzeniem typu obiektu.

 3
Author: Randolpho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:25:32

Używam go w binarnym serializerze (protobuf-net ). Używam reflection tylko do budowania modelu - gdy jest on używany (tj. podczas [de]serializacji )to używa delegatów itp dla maksymalnej wydajności.

Użyłem go również (wraz z ComponentModel i Reflection.Emit) w HyperDescriptor , aby zbudować przyspieszony dostęp do właściwości (~100x szybkość regularnego odbicia).

I z konieczności, musisz użyć reflection, jeśli jesteś budowanie własnych Expression s .

 3
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:39:19

Używam Reflection sporo w moich testach jednostkowych, zwłaszcza, gdy rzeczy, które sprawdzam są anonimowe typy. Użyłem go również jako sposobu na łatwe klonowanie / kopiowanie obiektów modelu. Zamiast pisać kod, aby to zrobić dla każdego obiektu modelu, mogę łatwo utworzyć obiekt określonego typu za pomocą refleksji, przesłuchać publiczne właściwości obiektu przychodzącego i wywołać ustawiacze na sklonowanych obiektach odpowiadające im właściwości. Używam go również z klasami generowanymi przez projektantów, które implementują te same podpisy metod, ale nie mają powiązanego interfejsu. W takich przypadkach mogę przesłuchać obiekt, aby sprawdzić, czy ma wymaganą metodę i wywołać go, jeśli tak. Encje LINQ2SQL są takie, więc w mojej metodzie wrapper onsubmit używam reflection, aby uzyskać metodę OnValidate i wywołać ją do testów jednostkowych.

 2
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:38:58

+ 1 na użycie wzorca fabrycznego -- bardzo mocne.

Pomijając wzór fabryczny, za każdym razem, gdy go używam, prawdopodobnie nie powinienem był...

Używałem go do dynamicznego ładowania klas implementujących określone interfejsy (moje były elementami menu z assemblies) przy starcie i naprawdę żałuję tego użycia. Szkoda, że nie załadowałem z pliku konfiguracyjnego (a później dodałem formularz, który pokazywał dostępne interfejsy do załadowania). Jest fajny, ale strasznie powolny...

Anty-wzorzec jest użycie właściwości dostępu, które projektanci klasy oznaczali jako prywatne, nie wiedząc, dlaczego oznaczyli je jako prywatne. Zrobiłem to za pomocą kontrolki DataGridView WinForms, aby odłączyć zmienną logiczną, dzięki czemu mogłem przenieść kolumnę "companion", gdy jej uzupełnienie zostało przeniesione. Po raz kolejny jest bardzo fajny ale ten kod się strasznie zawiedzie jeśli nowe wydanie zmieni tę własność prywatną (bardzo dobrze może zniknąć w 3.0 lub 3.5...).

 2
Author: Austin Salonen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:51:13

Poszedłem na 2 lata rozwoju, nie rozumiejąc celu refleksji. Ma bardzo niszowe zastosowania, ale jest niezwykle potężny, gdy jest właściwym narzędziem do pracy.

Myślę, że próbuję powiedzieć, że używaj go tylko wtedy, gdy jesteś pewien, że to jedyny sposób, aby osiągnąć to, czego chcesz.

 1
Author: Garry Shutler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:29:52

Używam go w przypadku podobnym do tego, o którym wspomniał Harper Shelby, w którym plik konfiguracyjny określa w czasie wykonywania, który obiekt ma utworzyć instancję. W moim konkretnym przypadku nie ma nic tak skomplikowanego jak fabryka--tylko zestaw klas, które implementują wspólny interfejs, i prosta funkcja, która odczytuje plik konfiguracyjny i tworzy właściwy obiekt, zwracając interfejs.

 1
Author: JSBձոգչ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 22:30:35

The prime place I use reflection: Pulling a type out of a database.

Mam klasę, która musi wiedzieć, do której biblioteki zadzwonić. Należy pamiętać, że gdy nowe narzędzia są dodawane do listy, klasa musi rozpoznawać nowe narzędzia bez rekompilacji, więc instrukcja switch nie wchodzi w grę.

Zamiast tego przechowuję łańcuch refleksyjny w DB, który mówi klasie, aby "utworzyła jedną z nich..."Ponieważ ja (programista) zawsze upewniam się, że klasa pochodzi z jednego klasa podstawowa, pomysł działa. Jest czysty i wydajny.

Ale Zgadzam się, że jeśli użyjesz reflection do czegoś więcej niż te scenariusze "auto-generowanego kodu", to możesz otworzyć się na świat bólu, jeśli chodzi o utrzymanie kodu w przyszłości.

(wpisz głos mądrego, starego mędrca)
Odbicie ma niesamowitą moc... użyj mocy z mądrością.

 1
Author: Jerry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-10 01:21:25

Używam go najczęściej, gdy muszę złamać enkapsulację innej osoby (zazwyczaj frameworka). Oznacza to, że muszę zmienić jakieś prywatne pole, wywołać prywatną metodę lub utworzyć instancję jakiejś wewnętrznej klasy w bibliotece, której nie mam uprawnień do zmiany. Dobrym przykładem jest kod w Moja odpowiedź na to pytanie . W tym przypadku zachowanie metody framework ServiceBase.Run było nie do przyjęcia, więc użyłem reflection, aby zrobić to samo, co robi w bardziej akceptowalnym sposób.

Reflection ma jednak wiele innych zastosowań, w tym pisanie kaczek , Praca z atrybutami i późne wiązanie .

 0
Author: P Daddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:45

Reflection pozwala na rozwiązywanie problemów, które w przeciwnym razie wymagałyby powielenia kodu. Jeśli znajdziesz się w kopiowaniu i wklejaniu kodu, a nie widzisz, jak wzór OO może pomóc, może jeśli możesz do nich zadzwonić ,to" zespół r " może pomóc.

Tylko żartowałem. Przez wieki nie rozumiałem sensu refleksji. Jeśli możesz napisać kod do wykonania zadania, dlaczego w ogóle musisz używać reflection?

Powiedzmy, że masz wiele obiektów GUI, takich jak formularze lub obiekty "tabeli". Wiąże się z obiekt biznesowy jak Klient:

public class Customer
{
   public string FirstName;
   public string LastName;

}

Twoi użytkownicy nie chcą widzieć nagłówków kolumn "FirstName" lub "LastName". Chcą "chrześcijańskiego imienia" i nazwiska. Nie chcesz kodować literalnych ciągów we wszystkich obiektach GUI w przypadku, gdy zmienią zdanie na "imię" i " nazwisko ojca "(wiem, gówniany przykład).

Jeśli zdefiniujesz klasę używając atrybutów:

public class Customer
{
   [Description("Christian Name")]
   public string FirstName;

   [Description("Surname")]
   public string LastName;

}

Możesz użyć reflection, aby wyciągnąć nazwy kolumn. Jeśli chcesz zmienić sposób wszystkie twoje obiekty GUI opisują obiekt klienta, teraz robisz to w jednym miejscu.

Nie znam żadnych anty-wzorców. Moja rada to wskoczyć i spróbować. Zaczniesz dostrzegać różne sposoby, w jakie odbicie daje Ci eleganckie rozwiązanie. Wydajność jest często cytowana jako powód, dla którego nie używa się relfection. Istnieje narzut wydajności z relfection, ale dyskontowałbym go, chyba że możesz udowodnić, że narzut szkodzi algorytmowi, którego potrzebujesz.
 0
Author: Jimmy McNulty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-09 23:10:10

Gdy chcesz poprawić wydajność obiektów późno związanych. Możesz emitować kod niezbędny do bezpośredniego wywołania typów powiązanych, a następnie wywołać za pomocą emitowanej metody. Chociaż nie możesz wykonywać połączeń tak szybko, jak w przypadku wczesnego wiązania, wykonasz je lepiej niż w przypadku późnego wiązania.

 0
Author: Rohit Vipin Mathews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-15 05:05:21

Osobiście nie używam go zbyt często. Używam go, gdy nie mam innego sposobu na zakodowanie czegoś.

Oto prosty przykład:

public static void LogException(Exception exc, string source)
{
    try
    {
        // Logic for logging exceptions
    }
    catch(Exception ex)
    {
        //If logging fails  for some reason 
        //then we still log it using reflection
        LogException(ex, "Error while logging an exception");
    }
}
 0
Author: meda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-20 17:09:46