Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
1
Programowanie zaawansowane
Refleksja
2
Wprowadzenie Pakiety są podstawowymi jednostkami wdrożeniowymi w świecie .NET. Za pomocą narzędzi środowiska programistycznego (IDE), jesteśmy w stanie obejrzeć wszystkie typy zdefiniowane w pakietach. Zewnętrzne narzędzia, takie jak ildasm i reflector pozwalają na przejrzenie kodu CIL, metadanych typów i manifestu pakietu dla wskazanych binariów .NET.
3
Zagadnienia (1) Oprócz tego, dostępnego w czasie projektowania, sposobu przeglądania zawartości pakietów, mamy również możliwość programowego dostępu do tych informacji wykorzystując przestrzeń nazw System.Reflection. Pierwszym omawianym zagadnieniem będzie rola refleksji i konieczność definiowania metadanych. Pozostałe zagadnienia będą ściśle związane z usługami refleksji.
4
Zagadnienia (2) Wykorzystanie dynamicznego ładowania i późnego wiązania w celu aktywowania typów, o których nie mamy żadnej wiedzy w czasie kompilacji. Dodawanie własnych metadanych do pakietu poprzez użycie dostarczanych przez system lub własnoręcznie zdefiniowanych atrybutów. Przykładowa aplikacja pokazująca zastosowanie poznanych mechanizmów.
5
Metadane i refleksja
6
Znaczenie metadanych (1)
Zdolność kompletnego opisywania typów (klas, interfejsów, struktur, enumeracji i delegatów) jest jednym z kluczowych elementów platformy .NET. Wiele technologii .NET, takich jak: Serializacja obiektów, Zdalne wywołania, XML-owe usługi sieciowe, Windows Communication Fundation (WCF) wymaga możliwości wykrywania formatu typów w czasie wykonania.
7
Znaczenie metadanych (2)
Na metadanych opiera się również: Współpraca w ramach wielojęzykowej platformy, Liczne usługi kompilatora, Możliwości narzędzi takich jak IntelliSense. Dzięki tak dużemu zastosowaniu metadanych są one znane i stosowane nie od dziś, w środowiskach takich jak np.: Java, CORBA, COM.
8
Zawartość metadanych (1)
Metadane przechowywane są w formie binarnej pozwalającej na duże upakowanie informacji. Programy służące do ich przeglądania wyświetlają te informacje w bardziej opisowej formie, czytelnej dla człowieka. Każdy typ zdefiniowany w aktualnym pakiecie jest udokumentowany za pomocą elementu TypeDef #n (ang. type definition). Typ, do którego się odnosimy jest udokumentowany za pomocą elementu TypeRef #n (ang. type reference).
9
Zawartość metadanych (2)
W sumie, metadane to zbiór tabel, zawierających ściśle sformatowane opisy wszystkich definicji typów i elementów powiązanych. Przykładowy opis typu (enumeracji):
10
Opis elementu TypeDef (1)
Definicja klasy i pola danych
11
Opis elementu TypeDef (2)
Definicja metody
12
Opis elementu TypeDef (3)
Definicja właściwości.
13
Opis elementu TypeRef Metadane zawierają wykaz typów zdefiniowanych w zewnętrznych pakietach, a do których odnosimy się w naszym projekcie.
14
Opis elementu Assembly
Do metadanych należy również opis pakietu (jego manifest).
15
Opis elementu AssemblyRef
Metadane zawierają także informacje o pakietach, z których korzystamy.
16
Opis elementu User Strings
Każdy łańcuch znakowy, zapisany w kodzie bazowym naszego projektu jest również zapisywany w metadanych
17
Refleksja Refleksja jest procesem odkrywania i wykorzystywania typów w czasie wykonania programu. Korzystając z usług refleksji, możliwe jest programowe zdobycie tej samej wiedzy o metadanych, którą uzyskujemy stosując zewnętrzne programy. Informacje te są prezentowane w postaci odpowiednio zaprojektowanych klas. Typy reprezentujące te informacje, zostały zdefiniowane w przestrzeni naw System.Reflection.
18
Zastosowanie refleksji
Za pomocą refleksji możemy (np.): Pozyskać listę wszystkich typów zawartych w danym pakiecie, włącznie z: Metodami, Polami danych, Właściwościami. Zdarzeniami zdefiniowanymi w ramach danego typu. Dynamicznie odkryć zbiór interfejsów wspieranych przez dany typ, parametry metod, I inne powiązane z tym szczegóły (klasy bazowe, informacje o przestrzeniach nazw, dane z manifestu itd.).
19
Przestrzeń nazw System.Reflection
Nazwa Typu Znaczenie Assembly Typ ten zawiera wiele metod pozwalających na ładowanie, przeglądanie i manipulowanie pakietami. AssemblyName Przechowuje informacje związane z identyfikacją pakietu (nazwa, wersja, lokalizacja itd.) EventInfo Przechowuje informacje o danym zdarzeniu. FieldInfo Przechowuje informacje o danym polu. MemberInfo Abstrakcyjna klasa bazowa, która definiuje wspólne zachowanie dla typów EventInfo, FieldInfo, MethodInfo, i PropertyInfo. MethodInfo Przechowuje informacje o danej metodzie. Module Pozwala na dostęp do danego modułu w wieloplikowym pakiecie. ParameterInfo Przechowuje informacje o danym parametrze. PropertyInfo Przechowuje informacje o danej właściwości.
20
Klasa System.Type Aby móc wykorzystać klasy zdefiniowane w przestrzeni nazw System.Reflection, musimy również znać typ System.Type. Klasa System.Type definiuje wiele składowych, które można użyć do zapoznania się z metadanymi typu. Duża część tych składowych zwraca obiekty typów zdefiniowanych właśnie w przestrzeni nazw System.Reflection.
21
Właściwości klasy System.Type
Nazwa właściwości Znaczenie IsAbstract IsArray IsClass IsCOMObject IsEnum IsGenericTypeDefinition IsGenericParameter IsInterface IsPrimitive IsNestedPrivate IsNestedPublic IsSealed IsValueType Te właściwości (nie wszystkie zostały tu przedstawione) pozwalają na zdobycie wielu informacji o podstawowych cechach danego typu (czy jest on abstrakcyjną klasą, zagnieżdżoną klasą, tablicą, itd.).
22
Metody klasy System.Type
Nazwa metody Znaczenie GetConstructors() GetEvents() GetFields() GetInterfaces() GetMembers() GetMethods() GetNestedTypes() GetProperties() Metody te pozwalają na pobranie tablicy reprezentującej elementy (interfejsy, metody, właściwości, itd.), o których chcemy pozyskać informacje. Każda z tych metody posiada również swoją pojedynczą odmianę, która zwraca konkretny element na podstawie wskazanej nazwy, a nie tablicę elementów danego rodzaju. FindMembers() Ta metod zwraca tablicę obiektów MemberInfo w oparciu o zadane kryteria. GetType() Ta statyczna metoda zwraca instancję Typu o zadanej poprzez łańcuch znaków nazwie. InvokeMember() Ta metoda umożliwia realizację późnego wiązania.
23
Metoda System.Object.GetType()
Instancję klasy Type możemy uzyskać na kilka sposobów. Czego nie możemy zrobić ,to ją zdefiniować poprzez słowo kluczowe new, ponieważ klasa Type jest klasą abstrakcyjną. Klasa System.Object definiuje metodę GetType(), która zwraca instancję obiektu klasy Type, reprezentującą metadane wskazanego typu. W tym przypadku musimy znać dany typ już podczas kompilacji.
24
Metoda Type.GetType() (1)
Aby zdobyć informacje o typie w bardziej elastyczny sposób, możemy skorzystać ze statycznej metody GetType() zdefiniowanej w klasie System.Type. Parametrem tej metody jest łańcuch znaków reprezentujący pełną kwalifikowaną nazwę danego typu. Używając tego podejścia, nie musimy znać definicji danego typu w czasie kompilacji. Sama nazwa typu może być, na przykład, dostarczona poprzez plik konfiguracyjny.
25
Metoda Type.GetType() (2)
Metoda GetType() posiada przeładowaną wersję z dwoma dodatkowymi argumentami logicznymi. Pierwszy decyduje o tym, czy odpowiedni wyjątek ma być zgłoszony w przypadku nieodnalezienia odpowiedniego typu. Drugi mówi o tym, czy metoda ma być niewrażliwa na wielkość liter w nazwie typu.
26
Metoda Type.GetType() (3)
W poprzednim przykładzie nic nie wskazywało na pakiet, w którym dany typ jest zdefiniowany. W takim przypadku zakłada się, że dany typ znajduje się w aktualnie tworzonym pakiecie. Gdy chcemy pobrać informacje z zewnętrznego pakietu, jego nazwę podajemy jako część łańcucha znaków definiującego nazwę typu, oddzieloną przecinkiem od samej kwalifikowanej nazwy typu. Dodatkowo , możemy użyć znaku „+” pozwalającego na pobranie zagnieżdżonej definicji typu.
27
Operator typeof Ostatnim sposobem uzyskania informacji o typie, jest wykorzystanie operatora typeof. Podobnie, jak w przypadku metody Type.GetType() nie musimy tworzyć obiektu danego typu, aby pobrać o nim informacje. Jednakże w tym przypadku kompilator musi mieć dostęp do definicji danego typu, ponieważ argumentem tej metody jest silnie typowana nazwa typu, a nie łańcuch znaków.
28
Dynamiczne ładowanie pakietów i późne wiązanie
29
Dynamiczne ładowanie pakietów
Dynamicznym ładowaniem nazywamy czynność ładowania zewnętrznego pakietu na żądanie. Przestrzeń nazw System.Reflection definiuje klasę Assembly, reprezentującą informacje i metody dotyczace pakietów.. Klasa ta definiuje metody (w szczególności Load() i LoadFrom()), które pozwalają na programowe wykorzystanie informacji, najczęściej definiowanych w pliku konfiguracyjnym po stronie klienta.
30
Przeglądarka zewnętrznych pakietów (1)
31
Przeglądarka zewnętrznych pakietów (2)
32
Późne wiązanie Późne wiązanie to technika pozwalająca na stworzenie instancji danego typu i wywołanie jego składowych w czasie wykonania programu bez posiadania wiedzy o tym typie w czasie kompilacji. Jeżeli jest to tylko możliwe, powinno się stosować „wczesne wiązanie” (czyli dodanie do projektu odwołania do odpowiedniego pakietu i tworzenie obiektów poprzez new). Pozwala ono na wykrycie błędów w czasie kompilacji. Jednakże, późne wiązanie odgrywa krytyczną role podczas tworzenia rozszerzalnych aplikacji.
33
Klasa System.Activator
Kluczową klasą używaną do późnego wiązania jest klasa System.Activator. Definiuje ona mały zbiór składowych, z których cześć jest używana w zdalnym API .NET. Interesującą nas metodą jest Activator.CreateInstancce(), która jest stosowana do utworzenia instancji typu w późnym wiązaniu. Metoda ta posiada wiele przeładowanych wersji. Najprostsza z nich przyjmuje jako argument obiekt klasy Type, reprezentujący typ, którego instancję chcemy stworzyć „w locie”.
34
Przykład utworzenia instancji „w locie”
35
Późne wywołanie metody (1)
Aby wywołać składową utworzonego w ten sposób obiektu, należy posłużyć się refleksją.
36
Późne wywołanie metody (2)
Parametry do późno wywoływanej metody przekazujemy jako tablicę obiektów klasy System.Object.
37
Atrybuty
38
Atrybuty (1) Zadaniem kompilatora jest wygenerowanie metadanych opisujących wszystkie zdefiniowane i wykorzystywane typy. Platforma .NET umożliwia również programiście dodanie własnych informacji do metadanych za pomocą atrybutów. Atrybuty to po prostu adnotacja kodu, która może być zastosowana do: Typu (klasy, interfejsu, struktury, itd.), Składowej (właściwości, metody, itd.), Pakietu, Modułu.
39
Atrybuty (2) Atrybuty na platformie .NET to klasy, które rozszerzają abstrakcyjna klasę bazową System.Attribute. W różnych przestrzeniach nazw zdefiniowanych jest wiele atrybutów, z których możemy skorzystać. Dodatkowo, możemy również tworzyć własne atrybuty. Informacje umieszczone w metadanych przy pomocy atrybutów są praktyczne bezużyteczne do momentu, w którym inny program użyje jawnie refleksji do odczytania tych danych.
40
Atrybuty standardowe Atrybuty Znaczenie [CLSCompilet] Wymusza sprawdzenie zgodności danego elementu ze specyfikacją CLS. [DllImport] Pozwala na odwołania do niezarządzanego kodu C i C++. [Obsolete] Oznacza dany element jako „przestarzały”. [Serializable] Oznacza daną klasę lub strukturę jako serializowalną (jej stan może być przekazany do strumienia. [NonSerialized] Oznacza, że dana składowa powinna być pominięta w procesie serializacji. [WebMethod] Oznacza metodę jako mogącą zostać wywołaną poprzez żądanie HTTPi instruuje CLR do serializacji wartości zwracanej przez daną metodę do XML-a.
41
Przykład użycia atrybutu (1)
Oznaczamy definiowaną klasę, jako mogącą zostać zapisaną do strumienia.
42
Przykład użycia atrybutu (2)
Pojedynczy element, może być oznaczony kilkoma atrybutami. Atrybuty te można również zapisać w następującej postaci:
43
Konstruktor atrybutu Atrybuty (jak wszystkie inne klasy), mogą posiadać konstruktory. Należy pamiętać, że w momencie nadania wartości parametrowi konstruktora, nie jest alokowany nowy obiekt w pamięci. Czynność ta jest realizowana dopiero w momencie odczytania atrybutu poprzez refleksję.
44
Skrótowy zapis Równie dobrze, można w nazwie atrybutu użyć pełnej nazwy klasy. Należy pamiętać, że nie wszystkie języki platformy .NET wspierają skrótowy zapis atrybutów (tak, jak czyni to C#).
45
Atrybut w akcji Następująca linie kodu:
Spowoduje pojawienie się ostrzeżeń
46
Podsumowanie atrybutów
Atrybuty prowadzą do dodanie informacji do metadanych. Atrybuty są klasami dziedziczącymi po klasie System.Attribute. Atrybuty są praktycznie bezużyteczne do momentu, gdy inny program odwoła się do nich poprzez refleksję. W C#, atrybuty definiujemy za pomocą nawiasów kwadratowych.
47
Niestandardowe atrybuty (1)
Definiujemy niestandardowy atrybut.
48
Niestandardowe atrybuty (2)
Użycie niestandardowego atrybutu.
49
Nazwane właściwości W przypadku pierwszej klasy, atrybut zdefiniowano za pomocą nazwanej właściwości Nazwana właściwość definiowana jest w postaci par nazwa/wartość. W momencie zastosowania refleksji, wskazana wartość przekazywana jest do odpowiedniej właściwości. Wymaga to oczywiście, aby w klasie atrybutu dana właściwość była zdefiniowana. Atrybuty przy pozostałych klasach definiowane są za pomocą konstruktorów.
50
Ograniczenie użycia atrybutu
Możliwe użycie atrybut ograniczamy za pomocą atrybutu AttributeUsage i enumeracji AttributeTargets.
51
Atrybuty i wczesne wiązanie
52
Atrybuty i późne wiązanie (1)
53
Atrybuty i późne wiązanie (2)
54
Przykład rozszerzalnej aplikacji
55
Tworzenie rozszerzalnej aplikacji
Po pierwsze, rozszerzalna aplikacja musi zapewnić pewien rodzaj wejścia, aby umożliwić użytkownikowi podłączenie pluginu (takie jak okienko dialogowe lub parametr w linii poleceń). To wymaga dynamicznego ładowania. Po drugie, rozszerzalna aplikacja musi być w stanie ustalić, czy moduł wspiera właściwą funkcjonalność (np. poprzez zbiór wymaganych interfejsów). To pozwoli na podłączenie go do środowiska. To wymaga refleksji. W końcu, rozszerzalna aplikacja musi pozyskać odwołanie do wymaganej infrastruktury (np. zbiór interfejsów) i wywołać jego składowe w celu „wystartowania” jego funkcjonalności. To wymaga późnego wiązania
56
Pakiety zdefiniowane w przykładzie
CommonSnappableTypes.dll – zawiera typy wykorzystywane przez wszystkie pluginy. CSharpSnapIn.dll – plugin w języku C#, VbNetSnapIn.dll - plugin w języku Visual Basic, MyExtendableApp.exe – aplikacja Windows Forms będzie właśnie rozszerzalną aplikacją, do której zostały napisane pluginy.
57
CommonSnappableTypes
58
CSharpSnapIn
59
VbNetSnapIn
60
MyExtendableApp (aplikacja Windows Forms)
61
MyExtendableApp (1) Zdarzenie kliknięcia na element w menu:
62
MyExtendableApp (2) Metoad loadExternalModule() (1)
63
MyExtendableApp (3) Metoad loadExternalModule() (2)
64
MyExtendableApp (4) W celu wyświetlenia informacji przekazanych poprzez atrybut, dodajemy do metody LoadExternalModul() wywołanie metody DisplayCompanyData().
65
MyExtendableApp (5) Definicja metody DisplayCompanyData().
66
MyExtendableApp (6)
67
Dziękuję za uwagę
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.