Chciałbym wiedzieć, czy można uzyskać atrybuty enum
wartości, a nie enum
samego? Załóżmy na przykład, że mam następujące elementy enum
:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
To, czego chcę, to typ wyliczenia, wykonanie 2 krotek wartości ciągu wyliczeniowego i jego opis.
Wartość była łatwa:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
Ale jak uzyskać wartość atrybutu opisu, aby wypełnić Tuple.Desc
? Mogę wymyślić, jak to zrobić, jeśli atrybut należy do enum
samego siebie, ale nie wiem, jak go zdobyć z wartości enum
.
c#
reflection
enums
.net-attributes
Alex K.
źródło
źródło
DescriptionAttribute
.Odpowiedzi:
To powinno zrobić to, czego potrzebujesz.
źródło
Ten fragment kodu powinien dać ci miłą małą metodę rozszerzenia na dowolnym wyliczeniu, która pozwala ci pobrać ogólny atrybut. Uważam, że różni się od powyższej funkcji lambda, ponieważ jest prostszy w użyciu i nieco - wystarczy podać typ ogólny.
źródło
IndexOutOfRangeException
?GetCustomAttributes()
a następnie zdobywania pierwszego elementu zamiast dzwonieniaGetCustomAttribute()
?Jest to ogólna implementacja wykorzystująca do wyboru lambda
Nazwij to tak:
źródło
FlagsAttribute
). W takim przypadkuenumeration.GetType().GetMember(enumeration.ToString())[0]
zawiedzie.value.GetType().GetField(value.ToString()).GetCustomAttributes(false).OfType<T>().SingleOrDefault()
ale musisz przyznać, że twój wyraźny sposób jest lepszy.Połączyłem tutaj kilka odpowiedzi, aby stworzyć nieco bardziej elastyczne rozwiązanie. Zapewniam to na wypadek, gdyby było to pomocne dla kogokolwiek innego w przyszłości. Oryginalny post tutaj .
To rozwiązanie tworzy parę metod rozszerzenia w Enum. Pierwszy pozwala użyć odbicia do pobrania dowolnego atrybutu związanego z twoją wartością. Drugi konkretnie wywołanie pobiera
DescriptionAttribute
i zwraca goDescription
wartość.Jako przykład rozważ użycie
DescriptionAttribute
atrybutu zSystem.ComponentModel
Aby użyć powyższej metody rozszerzenia, wystarczy teraz wywołać następujące polecenie:
lub
źródło
Oprócz odpowiedzi AdamCrawford , stworzyłem bardziej wyspecjalizowane metody rozszerzenia, które dostarczają go, aby uzyskać opis.
stąd, aby uzyskać opis, możesz użyć oryginalnej metody rozszerzenia jako
lub możesz po prostu wywołać metodę rozszerzenia tutaj jako:
Co, mam nadzieję, powinno uczynić twój kod nieco bardziej czytelnym.
źródło
Płynna jedna wkładka ...
Tutaj używam tego,
DisplayAttribute
który zawiera zarówno właściwościName
iDescription
.Przykład
Wynik
źródło
Oto kod, aby uzyskać informacje z atrybutu Display. Korzysta z ogólnej metody pobierania atrybutu. Jeśli atrybut nie zostanie znaleziony, konwertuje wartość wyliczeniową na ciąg znaków z przypadkiem pascal / camel przekonwertowanym na tytuł (otrzymany tutaj kod )
A to jest metoda rozszerzenia ciągów do konwersji na wielkość liter:
źródło
Zaimplementowałem tę metodę rozszerzenia, aby uzyskać opis z wartości wyliczeniowych. Działa dla wszystkich rodzajów wyliczeń.
źródło
Pobierz słownik z enum.
Teraz nazywaj to jak ...
Metoda rozszerzenia EnumDecription
źródło
Oto wersja .NET Core odpowiedzi AdamCrawford, wykorzystująca System.Reflection.TypeExtensions ;
źródło
Dodanie mojego rozwiązania dla Net Framework i NetCore.
Użyłem tego do mojej implementacji Net Framework:
To nie działa dla NetCore, więc zmodyfikowałem go, aby to zrobić:
Przykład wyliczenia:
Przykładowe użycie dla dodanego statycznego:
źródło
Korzystając z niektórych nowszych funkcji języka C #, możesz zmniejszyć liczbę wierszy:
źródło
Mam tę odpowiedź, aby skonfigurować pole kombi z atrybutów wyliczania, co było świetne.
Następnie musiałem zakodować odwrotną stronę, aby uzyskać wybór z pola i zwrócić wyliczenie we właściwym typie.
Zmodyfikowałem również kod, aby obsługiwał przypadek, w którym brakowało atrybutu
Dla korzyści następnej osoby, oto moje ostateczne rozwiązanie
}
źródło
Jeśli
enum
zawiera wartość, na przykładEquals
możesz napotkać kilka błędów przy użyciu rozszerzeń w wielu odpowiedziach tutaj. Wynika to z tego, że zwykle przyjmuje się,typeof(YourEnum).GetMember(YourEnum.Value)
że zwróci tylko jedną wartość, która jestMemberInfo
twojąenum
. Oto nieco bezpieczniejsza wersja odpowiedź Adama Crawforda .źródło
Ta metoda rozszerzenia uzyska ciąg reprezentujący wartość wyliczeniową za pomocą swojego XmlEnumAttribute. Jeśli nie ma XmlEnumAttribute, wraca do enum.ToString ().
źródło
A jeśli chcesz mieć pełną listę nazwisk, możesz zrobić coś takiego
źródło
Faceci, jeśli to pomoże, podzielę się z Wami moim rozwiązaniem: Definicja niestandardowego atrybutu:
Teraz, ponieważ potrzebowałem go w definicji HtmlHelper rozszerzenia HtmlHelper:
Mam nadzieję, że to pomoże
źródło
Teraz spowoduje błąd w tym przypadku 1 „równa się”
więc jeśli jest taka sama, zwracaj nazwę wyliczenia zamiast nazwy wyświetlanej, ponieważ enumMember.GetCustomAttribute () staje się pusty, jeśli nazwa wyświetlana i nazwa wyliczenia są takie same .....
źródło
Alternatywnie możesz wykonać następujące czynności:
źródło
W ten sposób rozwiązałem go bez użycia niestandardowych pomocników lub rozszerzeń w .NET core 3.1.
Klasa
Brzytwa
źródło
Wydajność ma znaczenie
Jeśli chcesz uzyskać lepszą wydajność, możesz to zrobić:
Dlaczego ma to lepszą wydajność?
Ponieważ wszystkie wbudowane metody używają kodu bardzo podobnego do tego, z wyjątkiem tego, że uruchamiają także wiele innych kodów, na których nam nie zależy . Kod Enum w C # jest ogólnie dość okropny.
Powyższy kod został opracowany przez Linq i usprawniony, więc zawiera tylko te bity, na których nam zależy.
Dlaczego wbudowany kod działa wolno?
Najpierw dotyczy Enum.ToString () -vs- Enum.GetName (..)
Zawsze używaj tego drugiego. (Lub jeszcze lepiej ani jedno, jak okaże się poniżej.)
ToString () używa tego ostatniego wewnętrznie, ale znowu robi też kilka innych rzeczy, których nie chcemy, np. Próbuje łączyć flagi, drukować liczby itp. Interesują nas tylko stałe zdefiniowane w wyliczeniu.
Enum.GetName z kolei pobiera wszystkie pola, tworzy tablicę ciągów dla wszystkich nazw, używa powyższego ToUInt64 na wszystkich swoich RawConstantValues do utworzenia tablicy UInt64 wszystkich wartości, sortuje obie tablice zgodnie z wartością UInt64, a na końcu pobiera nazwę z tablicę nazw, wykonując BinarySearch w tablicy UInt64, aby znaleźć indeks żądanej wartości.
... a następnie wyrzucamy pola, a posortowane tablice używają tej nazwy, aby ponownie znaleźć pole.
Jedno słowo: „Ugh!”
źródło
Alternatywnie możesz wykonać następujące czynności:
I uzyskaj opis z następującymi:
Moim zdaniem jest to bardziej efektywny sposób robienia tego, co chcesz osiągnąć, ponieważ nie ma potrzeby refleksji.
źródło
Możesz także zdefiniować wartość wyliczenia, np.
Name_Without_Spaces
I kiedy chcesz użyć opisu,Name_Without_Spaces.ToString().Replace('_', ' ')
aby zastąpić podkreślenia spacjami.źródło