2009-10-16 13 views
7

chcę mieć enum jak w:Możliwe, że masz ciągi do wyliczenia?

enum FilterType 
{ 
    Rigid = "Rigid", 
    SoftGlow = "Soft/Glow", 
    Ghost = "Ghost", 
} 

Jak to osiągnąć? Czy jest lepszy sposób to zrobić? Zostanie użyty dla instancji obiektu, gdzie będzie serializowany/deserializowany. Zapełni także listę rozwijaną.

Odpowiedz

11
using System.ComponentModel; 
enum FilterType 
{ 
    [Description("Rigid")] 
    Rigid, 
    [Description("Soft/Glow")] 
    SoftGlow, 
    [Description("Ghost")] 
    Ghost , 
} 

można uzyskać wartość z tak

public static String GetEnumerationDescription(Enum e) 
{ 
    Type type = e.GetType(); 
    FieldInfo fieldInfo = type.GetField(e.ToString()); 
    DescriptionAttribute[] da = (DescriptionAttribute[])(fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false)); 
    if (da.Length > 0) 
    { 
    return da[0].Description; 
    } 
    return e.ToString(); 
} 
+4

Przyjemne podejście. Możesz nawet mieć to jako metodę rozszerzenia dla wszystkich wyliczeń. –

+1

Dzięki .. Mam kilka statycznych metod, których używam w moim bieżącym projekcie, aby poradzić sobie z takimi wyliczeniami.Nigdy nie myślałem o używaniu metody rozszerzenia. Muszę spróbować. –

+0

Dobrą praktyką jest serializowanie tego poprzez ... definiowanie jeszcze jednego atrybutu .... w [System.Xml.Serialization.XmlEnum ("Rigid")] ... [Opis (" Sztywne ")] Sztywne, ... itd. –

1

To nie jest możliwe. C# zezwala tylko na zintegrowane typy wyliczeniowe (int, short, long, etc.). Możesz utworzyć lekką klasę "podobną do enum" lub użyć statycznych stałych.

static class FilterTypes 
{ 
    public const string Rigid = "Rigid"; 
    // ... 
} 

// or ... 

class FilterType 
{ 
    static readonly FilterType RigidFilterType = new FilterType("Rigid"); 

    string name; 

    FilterType(string name) // private constructor 
    { 
     this.name = name; 
    } 

    public static FilterType Rigid 
    { 
     get { return FilterType.RigidFilterType; } 
    } 

    // ... 
} 
+0

+1 za dodanie klasy lub struktury do zachowania się w ten sposób. –

0

Nie, to niemożliwe.

Zatwierdzone typy dla wyliczenia są bajt, sbyte, krótkie, ushort, int, uint długo lub Ulong.

Jednak można odzyskać deklarowaną nazwę wyliczenia z klasą ENUM:

string name = Enum.GetName(typeof(FilterType), FilterType.Rigid); 

Jeśli to nie zadziała, zbiór stałych łańcuchowych zebranych w potędze klasowej.

1

Wyliczenia są zawsze powiązane z wartością całkowitą. Więc nie. Możesz zrobić FilterType.Rigid.ToString(), aby uzyskać wartość ciągu, chociaż nie można go zlokalizować bezpośrednio.

9

Nie, ale jeśli chcesz, aby zakres „const” struny i używać ich jak wyliczenia, oto co robię:

public static class FilterType 
{ 
    public const string Rigid = "Rigid"; 
    public const string SoftGlow = "Soft/Glow"; 
    public const string Ghost ="Ghost"; 
} 
+0

Tak też zrobiłem w przeszłości, działa dobrze dla większości celów. – Chris

+1

Wadą tego podejścia jest to, że nie widzę sposobu, w jaki można automatycznie wypełnić listę rozwijaną. Przy odrobinie pracy masz przynajmniej opcję iterowania wartości enum. –

+0

@Michael: prawdopodobnie mógłbyś iterować z jakimś (niechlujnym) kodem odbitym. –

1

można uzyskać nazwę Enum jako ciąg jak ten

FilterType myType = FilterType.Rigid; 
String strType = myType.ToString(); 

Można jednak utknąć z oznaczeniem wielbłąda/węgierskim, ale można go łatwo przekonwertować na bardziej przyjazny dla użytkownika ciąg za pomocą metody podobnej do tej (Nie najładniejsze rozwiązanie, byłbym wdzięczny za informacje dotyczące optymalizacji tego). :

Public Shared Function NormalizeCamelCase(ByVal str As String) As String 

    If String.IsNullOrEmpty(str) Then 
     Return String.Empty 
    End If 

    Dim i As Integer = 0 
    Dim upperCount As Integer = 0 
    Dim otherCount As Integer = 0 
    Dim normalizedString As String = str 

    While i < normalizedString.Length 

     If Char.IsUpper(normalizedString, i) Then 
      ''Current char is Upper Case 
      upperCount += 1 
      If i > 0 AndAlso Not normalizedString(i - 1).Equals(" "c) Then 
       ''Current char is not first and preceding char is not a space 
       ''...insert a space, move to next char 
       normalizedString = normalizedString.Insert(i, " ") 
       i += 1 
      End If 
     ElseIf Not Char.IsLetter(normalizedString, i) Then 
      otherCount += 1 
     End If 

     ''Move to next char 
     i += 1 

    End While 

    If upperCount + otherCount = str.Length Then 
     ''String is in all caps, return original string 
     Return str 
    Else 
     Return normalizedString 
    End If 

End Function 

Jeśli to nadal nie jest wystarczająco ładna, można zajrzeć do Atrybuty niestandardowe, które mogą być pobierane przy użyciu odbicia ...

1

Nie, ale można oszukać tak:

public enum FilterType{ 
    Rigid, 
    SoftGlow, 
    Ghost 
} 

i wtedy, kiedy trzeba ich strln g wartości można po prostu zrobić FilterType.Rigid.ToString()

+1

Wykonywanie tego w ten sposób (co też jest winne) pokazuje tekst użytkownika bez spacji/znaków specjalnych (SoftGlow w przeciwieństwie do "Soft/Glow"), który jestem pewien, że chce móc to zrobić. – Pwninstein

0

Można użyć atrybutu nad wartościami

[System.ComponentModel.Description("Rigid")] 

przykład:

enum FilterType 
{ 
    [System.ComponentModel.Description("Rigid")] 
    Rigid, 
    [System.ComponentModel.Description("Soft/Glow")] 
    SoftGlow, 
    [System.ComponentModel.Description("Ghost")] 
    Ghost 
} 

i użyć refleksji uzyskać opisy.

Enum metodę rozszerzenia:

public static string GetDescription(this Enum en) 
    { 
     var type = en.GetType(); 
     var memInfo = type.GetMember(en.ToString()); 

     if (memInfo != null && memInfo.Length > 0) 
     { 
      var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); 
      if (attrs != null && attrs.Length > 0) 
       return ((DescriptionAttribute)attrs[0]).Description; 
     } 
     return en.ToString(); 
    } 

wykorzystanie go:

FilterType = FilterType.Rigid; 
      string description= result.GetDescription(); 
1

W nazw System.ComponentModel istnieje klasa DescriptionAttribute że działa dobrze tutaj.

enum FilterType 
{ 
    Rigid, 
    [Description("Soft/Glow")] 
    SoftGlow, 
    Ghost, 
} 

Następnie, aby uzyskać opis i fail over do toString()

var descriptionAttribute = Value.GetType() 
.GetField(Value.ToString()) 
.GetCustomAttributes(typeof(DescriptionAttribute), false) 
.OfType <DescriptionAttribute>() 
.FirstOrDefault()??new DescriptionAttribute(Value.ToString()); 
2

Jeśli jesteś wygodne z metod rozszerzenie, można łatwo zrobić to, co jesteś po:

//Can return string constants, the results of a Database call, 
//or anything else you need to do to get the correct value 
//(for localization, for example) 
public static string EnumValue(this MyEnum e) { 
    switch (e) { 
     case MyEnum.First: 
      return "First Friendly Value"; 
     case MyEnum.Second: 
      return "Second Friendly Value"; 
     case MyEnum.Third: 
      return "Third Friendly Value"; 
    } 
    return "Horrible Failure!!"; 
} 

W ten sposób można zrobić:

Private MyEnum value = MyEnum.First; 
Console.WriteLine(value.EnumValue()); 
0

Podobnie jak w przykładzie Shauna Bowe'a, możesz to również zrobić w C# 3 z metodą rozszerzenia dla enum (nie wymyśliłem i nie mogę, na moje życie, pamiętam, gdzie ja to zrobiłem).

utworzyć atrybut:

public class DisplayTextAttribute : Attribute { 
    public DisplayTextAttribute(String text) { 
    Text = text; 
    } 
    public string Text { get; set; } 
} 

Załóż rozszerzenie:

public static class EnumHelpers { 
    public static string GetDisplayText(this Enum enumValue) { 
    var type = enumValue.GetType(); 
    MemberInfo[] memberInfo = type.GetMember(enumValue.ToString()); 

    if (memberInfo == null || memberInfo.Length == 0) 
     return enumValue.ToString(); 

    object[] attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayTextAttribute), false); 
    if (attributes == null || attributes.Length == 0) 
     return enumValue.ToString(); 

    return ((DisplayTextAttribute)attributes[0]).Text; 
    } 
} 

Znalazłem to być rozwiązanie bardzo schludny. W swojej wyliczenia dodać następujące:

enum FilterType{ 
    Rigid, 
    [DisplayText("Soft/Glow")] 
    SoftGlow, 
    Ghost 
} 

Następnie można przejść FilterType.GetDisplayText() które odciągnąć ciąg dla Unattributed teksty stałe i displayText dla tych z atrybutami.

+0

Interesujące podejście. Upewnij się, że nie używasz tego kodu w ścieżce "wysokiej wydajności", ponieważ prowadzenie rozmów refleksyjnych jest dość kosztowne. – bobbymcr

1

To nie jest możliwe. Możesz jednak oszukać go za pomocą tablicy.

Najpierw utwórz ty ENUM drogę byś regularny jeden:

public enum Regexs 
{ 
    ALPHA = 0, 
    NUMERIC = 1, 
    etc.. 
} 

Następnie należy utworzyć tablicę, która przechowuje wartości odpowiadającej wartości ENUM:

private static string[] regexs = new string[] 
{ 
    "[A-Za-z]", 
    "[0-9]", 
    "etc"... 
} 

Następnie można uzyskać dostęp ciągi znaków przez wartość wyliczenia:

public void runit(Regexs myregexEnum) 
{ 
    Regex regex = new Regex(regexs [(int)myregexEnum]); 
} 
+0

Nie sądzę, że to rozwiązanie przynosi jakieś korzyści w stosunku do już przyjętej (dwa i pół roku) zaakceptowanej odpowiedzi, ponieważ teraz musisz zachować dwa miejsca zsynchronizowane, jeśli wprowadzisz jakiekolwiek zmiany w wyliczeniu. – Oliver

Powiązane problemy