2009-06-24 12 views
31

In Net è possibile scorrere un'enumerazione utilizzandoIterazione attraverso un'enumerazione in Silverlight?

System.Enum.GetNames(typeof(MyEnum)) 

o

System.Enum.GetValues(typeof(MyEnum)) 

In Silverlight 3 Tuttavia, Enum.GetNames e Enum.GetValues ​​non sono definiti. Qualcuno conosce un'alternativa?

+9

È ridicolo che questo non sia nel quadro. La dimensione del download non è una scusa per torturare gli sviluppatori. –

+0

se qualcuno ha bisogno, in particolare, di GetEnumValues ​​() e GetEnumNames(); Li ho implementati (in base alla risposta di ptoinson e Shimmy in basso) come risposta alla seguente domanda: http://stackoverflow.com/questions/7062208/how-do-i-create-a-getenumvalues-extension-method -in-silverlight-that-works-the-sa, e penso che siano equivalenti alle normali funzioni .NET (ma non Silverlight) con lo stesso nome. – shelleybutterfly

risposta

27

ho capito come fare questo senza fare ipotesi circa l'enum, imitando le funzioni in .Net:

public static string[] GetNames(this Enum e) { 
    List<string> enumNames = new List<string>(); 

    foreach (FieldInfo fi in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)){ 
     enumNames.Add(fi.Name); 
    } 

    return enumNames.ToArray<string>(); 
} 

public static Array GetValues(this Enum e) { 
    List<int> enumValues = new List<int>(); 

    foreach (FieldInfo fi in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)) { 
     enumValues.Add((int)Enum.Parse(e.GetType(), fi.Name, false)); 
    } 

    return enumValues.ToArray(); 
} 
+0

Buona soluzione +1! – stevehipwell

+1

Vorrei tuttavia suggerire di restituire un IList per il metodo migliore e un IList per il secondo. E ricorda che questo non supporterà enumerazioni che rappresentano un valore lungo. – stevehipwell

+2

È possibile supportare tipi non int che ottengono il tipo sottostante (Enum.GetUnderlyingType()) – dcstraw

3

Non l'ho provato, ma le API di riflessione dovrebbero funzionare.

1

Credo che questo sia lo stesso di .NET Compact Framework. Se si presuppone che i valori dell'enumerazione inizino a 0 e utilizzino ogni valore fino a quando il loro intervallo non si esaurisce, il seguente codice dovrebbe funzionare.

public static IList<int> GetEnumValues(Type oEnumType) 
{ 
    int iLoop = 0; 
    bool bDefined = true; 
    List<int> oList = new List<int>(); 

    //Loop values 
    do 
    { 
    //Check if the value is defined 
    if (Enum.IsDefined(oEnumType, iLoop)) 
    { 
     //Add item to the value list and increment 
     oList.Add(iLoop); 
     ++iLoop; 
    } 
    else 
    { 
     //Set undefined 
     bDefined = false; 
    } 
    } while (bDefined); 

    //Return the list 
    return oList; 
} 

Ovviamente si potrebbe modificare il codice per restituire i nomi enum o per abbinare i modelli diferent esempio valori bit a bit.

Ecco una versione alternativa del metodo che restituisce un IList<EnumType>.

public static IList<T> GetEnumValues<T>() 
{ 
    Type oEnumType; 
    int iLoop = 0; 
    bool bDefined = true; 
    List<T> oList = new List<T>(); 

    //Get the enum type 
    oEnumType = typeof(T); 

    //Check that we have an enum 
    if (oEnumType.IsEnum) 
    { 
    //Loop values 
    do 
    { 
     //Check if the value is defined  
     if (Enum.IsDefined(oEnumType, iLoop)) 
     { 
     //Add item to the value list and increment  
     oList.Add((T) (object) iLoop); 
     ++iLoop; 
     } 
     else 
     { 
     //Set undefined  
     bDefined = false; 
     } 
    } while (bDefined); 
    } 

    //Return the list 
    return oList; 
} 
+0

So che hai avuto l'avvertenza di assumere valori contigui, ma in particolare tutte le enumerazioni [Bandiere] attribuite non funzionerebbero. – dcstraw

+0

@dcstraw - Leggi l'ultima sentanza, ho riconosciuto che è possibile utilizzare un modello diverso per far corrispondere i valori bit a bit, ad es. [Flags]; per fare questo '++ iLoop;' diventa 'iLoop = iLoop << 1;'. – stevehipwell

+0

Una richiesta se non ti dispiace: dal momento che questo non restituisce una matrice di tipi specifici enumerati, ma invece una lista , in realtà non corrisponde al comportamento sulla piattaforma .NET e ha causato un bel po 'di confusione per me quando si cerca di determinare se questa funzione potrebbe funzionare per un altro utente. Saresti disposto a rinominarlo in qualcos'altro? Il problema principale per me è che GetArrayValues ​​(i) .ToString() restituisce una stringa del numero anziché il nome dell'enumerazione, come viene restituito dalla versione .NET effettiva, anche se sono sicuro che ci sono altre possibili fonti di confusione. – shelleybutterfly

30

O forse fortemente tipizzato utilizzando LINQ, in questo modo:

public static T[] GetEnumValues<T>() 
    { 
     var type = typeof(T); 
     if (!type.IsEnum) 
      throw new ArgumentException("Type '" + type.Name + "' is not an enum"); 

     return (
      from field in type.GetFields(BindingFlags.Public | BindingFlags.Static) 
      where field.IsLiteral 
      select (T)field.GetValue(null) 
     ).ToArray(); 
    } 

    public static string[] GetEnumStrings<T>() 
    { 
     var type = typeof(T); 
     if (!type.IsEnum) 
      throw new ArgumentException("Type '" + type.Name + "' is not an enum"); 

     return (
      from field in type.GetFields(BindingFlags.Public | BindingFlags.Static) 
      where field.IsLiteral 
      select field.Name 
     ).ToArray(); 
    } 
+1

Meglio mettere 'dove T: struct, IConvertible' nella definizione del metodo per avvicinarsi a limitare' T' solo alle enumerazioni. – Kamyar

Problemi correlati