Zdarzenia – wywołanie, wykorzystanie i obsługa

Zdarzenia

Jeśli chcemy, ażeby jakiś fragment kodu reagował na zdarzenia z innego obiektu musimy przypisać funkcję obsługującą zdarzenie. Metoda obsługująca zdarzenie powinna przyjmować  dwa parametry:

  • obiekt klasy Object, który informuje przez co zostało wywołane zdarzenie
  • obiekt z argumentami zdarzenia typu dziedziczącego po EventArgs

Przypisanie wygląda następująco

W pierwszym przypadku wykorzystujemy metodę do obsługi zdarzenia, a w drugim metodę anonimową. Jeśli nie chcemy więcej otrzymywać informacji o zdarzeniach powinniśmy się wypisać z listy metod informowanych o zdarzeniach przy pomocy operatora -=

Deklaracja własnego zdarzenia

W celu zadeklarowania własnego eventu wykorzystujemy

Deklaracja ta powinna się znajdować wewnątrz klasy, która będzie to zdarzenie udostepniać.

Wywołanie zdarzenia

Jeśli chcemy wywołać zdarzenia poprzez nasz kod musimy obowiązkowo sprawdzić czy ktoś je zasubskrybował. Obecnie takie wywołanie jest proste

Konstrukcja ta jest dostępna od C# w wersji 6. W poprzednich wersjach powinniśmy sprawdzić czy event nie jest null-em.

Wykorzystanie zmiennej lokalnej jest zalecane w celu zapewnienia, że żaden wątek nie zmodyfikuje nam wartości pomiędzy sprawdzeniem a wywołaniem zdarzenia.

 

 

 

Metoda using

Metoda using

Wykorzystywany jest w przypadkach, gdy pracujemy z obiektami, które powinny być w bezpieczny sposób usunięte z pamięc, i takich jak strumienie, readery czy połączenia sieciowego. W tym przypadku niezależnie od tego czy coś się stanie możemy wykorzystać blok try{}finally{}, o którym pisałem ostatnio https://mateuszstanek.pl/2018/02/13/obsluga-wyjatkow/ Czytaj dalej Metoda using

Yield – Leniwe kolekcje

Yield

Instrukcja Yield wykorzystywana jest do tworzenia kolekcji, gdzie kolejne elementy kolekcji są tworzone w momencie ich wykorzystania. Umożliwia to zaoszczędzenie pamięci oraz przyśpieszenie działania aplikacji. Jeśli chcemy wygenerować obiekty naszej listy możemy wykorzystać instrukcję yield return:

Metoda generująca nasze elementy zostanie wykonana dopiero w momencie odczytu elementu poprzez enumerator. Odczytem jest każda operacja, która pobiera wartość, i tak dla :

w wyniku otrzymamy

a gdy tylko będziemy chcieli odwrócić kolejność elementów przy pomocy reverse

otrzymamy

Jeśli chcemy zakończyć kolekcję w dowolnym momencie możemy wykorzystać yield break.

Zastosowanie

Leniwe kolekcje mogą być wykorzystane wszędzie tam, gdzie wykorzystujemy normalny IEnumerable, jednakże swoją potęgę pokazują, kiedy mamy do czynienia z dużymi zbiorami danych. Jeśli zbiór danych znajduje się na dysku w postaci pliku możemy odczytywać jego zawartość sekwencyjnie i zwracać dane w mniejszych partiach. Przy odczycie i zwróceniu od razu całej kolekcji w postaci listy, pełen zbiór danych musiałby zostać odczytany i przechowany w pamięci aplikacji.

Innym przypadkiem użycia może być trudna generacja danych dla kolekcji. Jeśli generacja takich danych jest trudna nie potrzebujemy od razu znać pełnej kolekcji, niekiedy potrzebujemy tylko kilka pierwszych wartości. Przy zastosowaniu listy musielibyśmy obliczyć od razu wszystkie elementy, a z wykorzystaniem yield elementy są obliczane wraz z postępem przetwarzania naszej kolekcji.

Obsługa wyjątków

Wyjątek

Wyjątek jest mechanizmem kontrolowania aplikacji w sytuacjach wyjątkowych, niespodziewanych czy błędnych. Dzięki niemu możemy odzyskać kontrolę nad aplikacją w momencie, kiedy użytkownik, bądź uwarunkowania zewnętrzne(poza aplikacją) nie działają tak jak tego się spodziewamy. Do obsługi wyjątków służy blok Czytaj dalej Obsługa wyjątków

Czytelne testy z FluentAssertions

FluentAssertions

FluentAssertions jest biblioteką, dzięki której assercje w testach są dużo bardziej czytelne. Osobiście używam jej, jeśli tylko mogę. Assercje z jej wykorzystaniem są łatwe do zrozumienia, a i komunikaty błędów są moim zdaniem czytelniejsze, niż w przypadku standardowych assercji. Czytaj dalej Czytelne testy z FluentAssertions

Program xsd.exe – pomoc przy pracy

Program xsd.exe jest dostarczany wraz z pakietem visual studio i możemy go uruchomić poprzez konsolę developerską na przykład (Developer Command Prompt for VS 2017) dostępną z menu start. Program ten jest bardzo przydatny, kiedy musimy wygenerować klasy do serializacji, a dysponujemy schemą xml-a lub też kompletnym plikiem xml. Pozwala nam to zautomatyzować żmudne wpisywanie klas obiektów serializowanych ręcznie jak opisaliśmy w  tym poście. W kolejnych akapitach postaram się powiedzieć jak wykorzystywać xsd.exe przy pracach związanych z serializacją xml-a.

Xml na schemę xsd

Pierwszym przypadkiem użycia będzie wykorzystanie możliwości stworzenia schemy xsd na podstawie pliku xml-owego.  W najprostszej formie możemy wywołać program z katalogu, gdzie mamy nasz plik
xml-owy i jako parametr podać tylko nazwę pliku wejściowego.

Naszym plikiem wejściowym będzie ostatnio wygenerowany plik xml

po wywołaniu polecenia

w tym samym katalogu otrzymamy schemę pliku SerializedObject.xsd

Xsd na klasę

Kolejnym krokiem jest wygenerowanie klas na podstawie schemy. To również jest zadaniem trywialnym. Tym razem oprócz parametru w postaci nazwy pliku xsd  wykorzystujemy przełączniki /c lub /class oraz  /language:languageName. Wspieranymi językami są :

  • C#(CS)  jest wartością domyślną w przypadku generacji klas C# przełącznik można pominąć
  • Visual Basic (VB)
  • JScript (JS)
  • Visual J# (VJS)

Nie są to pełne możliwości programu xsd.exe lecz najczęściej wykorzystywane, osobiście nie miałem okazji wykorzystać innych a i generację schemy wykorzystałem tylko 1 raz. Co innego generacja klas, z której korzystałem wiele razy. Więcej można przeczytać w dokumentacji https://docs.microsoft.com/en-us/dotnet/standard/serialization/xml-schema-definition-tool-xsd-exe

Serializacja i deserializacja XML-a

XML – czym jest?

XML, czyli Extensible Markup Language  jest popularnym sposobem zapisu danych w formie tekstowej. Przez drzewiastą strukturę i słowny zapis wartości oraz nazw właściwości jest łatwy do zrozumienia. Przy pracy z XML mamy kilka możliwości. Możemy go deserializować do postaci obiektów oraz serializować obiekty do xml-a. Możemy także załadować strukturę do pamięci i przetwarzać je z wykorzystaniem DOM API lub z wykorzystaniem nowszego LINQ to XML API. Dzisiaj skupię się na serializacji obiektów z wykorzystaniem wcześniej przygotowanych klas. Czytaj dalej Serializacja i deserializacja XML-a

Refleksja – manipulacja obiektami

Refleksja, manipulacja obiektami

W poprzedniej części odczytywaliśmy metadane przy pomocy refleksji. Dzisiaj wykorzystamy te dane, ażeby manipulować obiektami, tworzyć instancje oraz zmieniać ich właściwości, czy też wywoływać ich metody. To właśnie dzięki tym mechanizmom możliwa jest implementacja  kontenerów dependency injection  (wykorzystanie możliwości kreacji obiektów), czy też runnery testów (odczyt atrybutów metod oraz ich wywołanie). Czytaj dalej Refleksja – manipulacja obiektami

Refleksja – odczyt metadanych

Refleksja

Refleksja jest mechanizmem umożliwiającym odczytywanie metadanych. Dzięki niemu możemy odczytać atrybuty i własności obiektów w bibliotekach. Dzięki temu mechanizmowi możemy bez trudu odczytywać własne atrybuty tworzone jak w poprzednim wpisie https://mateuszstanek.pl/2018/02/04/wlasny-atrybut/ Czytaj dalej Refleksja – odczyt metadanych