Jakiś tydzień temu włączył mi się straszny leń i jakoś za nic nie mogę się zabrać. Żeby nie było, że bezczynnie siedziałem, bo nie lubię takiego wrażenia sprawiać, napiszę co nieco o takiej miłej rzeczy jaką są csharpowe atrybuty.
Zastanawiałem się w jaki sposób można je wykorzystać w mojej pracy i chyba znalazłem dość ciekawe zastosowanie. Używam ich w dwóch miejscach.
Po pierwsze jest to oznaczenie funkcji, które mogą być uruchamiane w procesie przetwarzania wiadomości otrzymanych (te wysyłane w zawartości wiadomości).
Po drugie z lenistwa i to chyba jest ciekawszy przykład. Nie chciało mi się do GUI wklepywać obsługi każdego generatora grafów, więc postanowiłem, że stworze sobie atrybut, który będzie opisywać mi każdy generator. Na jego podstawie tworzę panel, który daje możliwość wyboru generatora, podania parametrów (dowolna ilość) i sprawdza poprawność wprowadzonych danych (bo przecież każdy może się pomylić :P). Na początku (generatory GNP, GNK, GNF) sprawa z walidacją danych była prosta int.Parse lub float.Parse, niestety potem okazało się, że jest również generator typu GNC co znacznie skomplikowało sprawę. Jest to jedyny generator, który jako parametr przyjmuje tablice. Wprowadziłem więc dodatkowy parametr do atrybutu którym jest nazwa funkcji która ma być wywołana przy walidacji i uruchomieniu generatora. Potem trochę operacji na typach i refleksji i po sprawie. Całość zajęła mi pewnie więcej czasu niż wyklikanie okienek, ale to mało istotne.
No dobra dosyć przydługich wstępów, teraz o atrybutach. Przedstawię sprawę w punktach:
1. Tworzymy standardową klasę, której konstruktor może, ale nie musi mieć parametry. Tu uwaga bo okazuje się, że parametrami mogą być tylko wyrażenia stałe, wyrażenia typeof oraz typy tablicowe.
2. W tej klasie piszemy jakieś miłe getery do tego co potrzebne
3. Dodajemy do klasy dziedziczenie po System.Attribute
4. Przed definicją klasy ustawiamy atrybut AttributeUsage, tu możemy określić sobie do czego stosowalny jest nasz atrybut (intelisense jak zwykle nie zawiedzie), czy jeden element może mieć wiele atrybutów tej klasy oraz czy atrybut może być dziedziczony.
Na tym etapie mamy już gotową klasę atrybutu, ustawienie atrybutu to prosta sprawa, ale jak potem z niego skorzystać? Kawałek kodu będzie si w tym miejscu:
//Pobieramy klasę
Type generatorsClass = typeof(Generators);
//Pobieramy metody statyczne (generatory to metody statyczne)
MethodInfo[] generators = generatorsClass.GetMethods(BindingFlags.Static | BindingFlags.Public);
foreach (MethodInfo info in generators)
{
try
{
//Pobieramy atrybuty metody typu takiego jak nas interesuje (pierwszy parametr) oraz nie dziedziczone (drugi parametr) w rezultacie dostajemy tablicę atrybutów o długości zależnej od ilości zdefiniowanych atrybutów danego typu
GeneratorAttribute[] methodAttributes = (GeneratorAttribute[])info.GetCustomAttributes(typeof(GeneratorAttribute), false);
//Robimy coś z atrybutem
}
catch { }
}
To byłoby na tyle. Całkiem prosta sprawa, a może czasem pomóc.