2010-04-30 10 views
12

Ho scritto codice a TryParse enum in base al valore o al suo nome come mostrato di seguito. Come posso estendere questo codice per includere l'enumerazione dell'analisi con l'attributo Flags?Enum.TryParse con attributo Flags

public static bool TryParse<T>(this T enum_type, object value, out T result) 
       where T : struct 
      { 
       return enum_type.TryParse<T>(value, true, out result); 
      } 



public static bool TryParse<T>(this T enum_type, 
object value, bool ignoreCase, out T result) 
     where T : struct 
    { 
     result = default(T); 
     var is_converted = false; 

     var is_valid_value_for_conversion = new Func<T, object, bool, bool>[]{ 
      (e, v, i) => e.GetType().IsEnum, 
      (e, v, i) => v != null, 
      (e, v, i) => Enum.GetNames(e.GetType()).Any(n => String.Compare(n, v.ToString(), i) == 0) || Enum.IsDefined(e.GetType(), v) 
     }; 

     if(is_valid_value_for_conversion.All(rule => rule(enum_type, value, ignoreCase))){ 
      result = (T)Enum.Parse(typeof(T), value.ToString(), ignoreCase); 
      is_converted = true; 
     } 

     return is_converted; 
    } 

Attualmente questo codice funziona per le seguenti enumerazioni:

enum SomeEnum{ A, B, C } 
// can parse either by 'A' or 'a' 

enum SomeEnum1 : int { A = 1, B = 2, C = 3 } 
// can parse either by 'A' or 'a' or 1 or "1" 

Non funziona per:

[Flags] 
enum SomeEnum2 { A = 1, B = 2, C = 4 } // can parse either by 'A' or 'a' 
// cannot parse for A|B 

Grazie!

risposta

0

@ risposta di Pop mi ha dato un indizio & ho modificato le regole controllare nel mio codice per assomigliare:

var is_valid_value_for_conversion = new Func<T, object, bool, bool>[] 
{ 
    (e, v, i) => e.GetType().IsEnum, 
    (e, v, i) => value != null, 
    (e, v, i) => Enum.GetNames(e.GetType()).Any(
       n => String.Compare(n, v.ToString(), i) == 0 
       || (v.ToString().Contains(",") && v.ToString().ToLower().Contains(n.ToLower()))) 
       || Enum.IsDefined(e.GetType(), v) 
}; 

il resto rimanendo lo stesso e funziona per me

HTH qualcun altro

+1

Il controllo null non dovrebbe essere la tua prima regola? – ChaosPandion

+0

Primo controllo o secondo non farebbero differenza in questo caso IMO, a meno che manchi qualcosa, oltre al fatto che il vincolo è su struct, penso che dobbiamo verificare se la chiamata è su un tipo enum valido prima di verificare se il valore è nullo – Sunny

16

A partire da .NET 4, esiste un metodo Enum.TryParse<T>. Supporta Bandiere enumerazioni fuori dalla scatola:

string x = (SomeEnum2.A | SomeEnum2.B).ToString(); // x == "A, B" 
SomeEnum2 y; 
bool success = Enum.TryParse<SomeEnum2>(x, out y); // y == A|B 
+7

sì TryParse è esposto in 4.0, ero alla ricerca di una soluzione in 3,5 ... – Sunny

+0

perché non utilizzare Enum.Parse e wra p a try/catch block intorno ad esso? – yoyo

26

Bandiere enumerazioni sono scritti utilizzando , utilizzando la convenzione .Net e non |. Enum.Parse() funziona perfettamente quando si usa '' stringhe:

[Flags] 
public enum Flags 
{ 
    A = 1, 
    B = 2, 
    C = 4, 
    D = 8, 
} 

var enumString = (Flags.A | Flags.B | Flags.C).ToString(); 
Console.WriteLine(enumString); // Outputs: A, B, C 
Flags f = (Flags)Enum.Parse(typeof(Flags), enumString); 
Console.WriteLine(f); // Outputs: A, B, C