String reprezentacja Enum
Mam następujące wyliczenie:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
Problem polega jednak na tym, że potrzebuję słowa "formy", gdy proszę o uwierzytelnienie.Formularze, a nie id 1.
Znalazłem następujące rozwiązanie tego problemu ( link):
Najpierw muszę utworzyć własny atrybut o nazwie "StringValue":
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Wtedy mogę dodać ten atrybut do mojego enumeratora:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
I oczywiście potrzebuję czegoś, żeby to odzyskać StringValue:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
Dobrze, teraz mam narzędzia, aby uzyskać wartość ciągu Dla enumeratora. Mogę wtedy użyć go w ten sposób:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
/ Align = "left" / Zastanawiałem się, czy jest na to lepsze rozwiązanie.
Próbowałem też czegoś ze słownikiem i właściwościami statycznymi, ale to też nie było lepsze.
7 answers
Trytype-safe-enum pattern.
public sealed class AuthenticationMethod {
private readonly String name;
private readonly int value;
public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3, "SSN");
private AuthenticationMethod(int value, String name){
this.name = name;
this.value = value;
}
public override String ToString(){
return name;
}
}
Update Jawna (lub niejawna) konwersja typu może być wykonana przez
-
Dodawanie pola statycznego z mapowaniem
private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
- N. b. aby inicjalizacja pól " enum member "nie powodowała wystąpienia Nullreferencexception podczas wywoływania konstruktora instancji, należy umieścić pole słownika przed polami" enum member " w swojej klasie. Dzieje się tak dlatego, że inicjalizatory pola statycznego wywołane są w kolejności deklaracji, a przed konstruktorem statycznym, tworząc dziwną i konieczną, ale mylącą sytuację, w której konstruktor instancji może być wywołany przed zainicjalizowaniem wszystkich pól statycznych i przed wywołaniem konstruktora statycznego.
-
Wypełnianie tego mapowania w konstruktorze instancji
instance[name] = this;
-
Oraz dodanie operatora konwersji typu zdefiniowanego przez użytkownika
public static explicit operator AuthenticationMethod(string str) { AuthenticationMethod result; if (instance.TryGetValue(str, out result)) return result; else throw new InvalidCastException(); }
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
2015-03-12 08:25:53
Użyj metody
Enum.GetName(Type MyEnumType, object enumvariable)
Jak w (Załóżmy, że Shipper
jest zdefiniowanym Enum)
Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);
Jest kilka innych statycznych metod na klasie Enum, które warto zbadać...
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-12-28 14:33:40
Możesz odwoływać się do nazwy, a nie do wartości, używając ToString ()
Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());
Dokumentacja jest tutaj:
Http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
...a jeśli nazwiesz swoje enums w przypadku Pascala (tak jak ja - np. ThisIsMyEnumValue = 1 itd.) następnie możesz użyć bardzo prostego wyrażenia regularnego do wydrukowania przyjaznego formularza:
static string ToFriendlyCase(this string EnumString)
{
return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}
Które można łatwo wywołać z dowolnego ciągu znaków:
Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());
Wyjścia:
Convert My Crazy Pascal Case Sentence To Friendly Case
To oszczędza bieganie po domach tworzenie niestandardowych atrybutów i dołączanie ich do Twoich enum lub za pomocą tabel wyszukiwania, aby połączyć wartość enum z przyjaznym ciągiem, a najlepsze jest to samo zarządzanie i może być używane na każdym Pascalu Case string, który jest nieskończenie bardziej wielokrotnego użytku. Oczywiście nie pozwala to na posiadanie innej przyjaznej nazwy niż Twoje enum, które zapewnia Twoje rozwiązanie.
I do like your oryginalne rozwiązanie dla bardziej złożonych scenariuszy. Możesz wziąć swoje rozwiązanie o krok dalej i uczynić GetStringValue metodą rozszerzenia swojego enum, a następnie nie musisz odwoływać się do niego jak StringEnum.GetStringValue...
public static string GetStringValue(this AuthenticationMethod value)
{
string output = null;
Type type = value.GetType();
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
if (attrs.Length > 0)
output = attrs[0].Value;
return output;
}
Możesz wtedy łatwo uzyskać do niego dostęp bezpośrednio z instancji enum:
Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());
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-12 13:03:08
Niestety refleksja nad uzyskaniem atrybutów na enumach jest dość powolna:
Zobacz to pytanie: ktoś zna szybki sposób, aby dostać się do niestandardowych atrybutów na wartości enum?
.ToString()
jest również dość powolny na enumach.
Możesz jednak napisać metody rozszerzeń dla enum:
public static string GetName( this MyEnum input ) {
switch ( input ) {
case MyEnum.WINDOWSAUTHENTICATION:
return "Windows";
//and so on
}
}
To nie jest świetne, ale będzie szybkie i nie będzie wymagało odbicia dla atrybutów lub nazwy pola.
C # 6 Update
Jeśli możesz używać C # 6 to nowy nameof
operator działa dla enum, więc nameof(MyEnum.WINDOWSAUTHENTICATION)
zostanie przekonwertowany na "WINDOWSAUTHENTICATION"
w czasie kompilacji, co czyni go najszybszym sposobem uzyskania nazw enum.
Zauważ, że spowoduje to konwersję jawnego enum na stałą inlined, więc nie działa dla enum, które masz w zmiennej. Więc:
nameof(AuthenticationMethod.FORMS) == "FORMS"
Ale...
var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"
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 11:55:02
Używam metody rozszerzenia:
public static class AttributesHelperExtension
{
public static string ToDescription(this Enum value)
{
var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false);
return da.Length > 0 ? da[0].Description : value.ToString();
}
}
Teraz udekoruj enum
z:
public enum AuthenticationMethod
{
[Description("FORMS")]
FORMS = 1,
[Description("WINDOWSAUTHENTICATION")]
WINDOWSAUTHENTICATION = 2,
[Description("SINGLESIGNON ")]
SINGLESIGNON = 3
}
Kiedy zadzwonisz
AuthenticationMethod.FORMS.ToDescription()
dostaniesz "FORMS"
.
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
2014-06-05 15:08:01
Po prostu użyj metody ToString()
public enum any{Tomato=0,Melon,Watermelon}
Aby odwołać się do ciągu Tomato
, wystarczy użyć
any.Tomato.ToString();
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-09-24 17:33:54
Używam atrybutu Description z systemu.Przestrzeń nazw ComponentModel. Po prostu udekoruj enum, a następnie użyj tego kodu, aby go odzyskać:
public static string GetDescription<T>(this object enumerationValue)
where T : struct
{
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}
Jako przykład:
public enum Cycle : int
{
[Description("Daily Cycle")]
Daily = 1,
Weekly,
Monthly
}
Ten kod dobrze odpowiada enumom, w których nie potrzebujesz "przyjaznej nazwy" i zwrócisz tylko .ToString () z enum.