2009-02-03 6 views
52

Ho ottenuto un valore Int16 dal database e devo convertirlo in un tipo di enum. Questo è sfortunatamente fatto in uno strato del codice che sa molto poco degli oggetti, tranne per quello che può raccogliere attraverso la riflessione.Convert.ChangeType e conversione in enumerazione?

Come tale, termina chiamando Convert.ChangeType che non riesce con un'eccezione di cast non valida.

ho trovato quello che considero una soluzione puzzolente, in questo modo:

String name = Enum.GetName(destinationType, value); 
Object enumValue = Enum.Parse(destinationType, name, false); 

C'è un modo migliore, in modo che non devo per muoversi attraverso questa operazione String?

Ecco una breve, ma completo, il programma che può essere utilizzato, se qualcuno ha bisogno di sperimentare:

using System; 

public class MyClass 
{ 
    public enum DummyEnum 
    { 
     Value0, 
     Value1 
    } 

    public static void Main() 
    { 
     Int16 value = 1; 
     Type destinationType = typeof(DummyEnum); 

     String name = Enum.GetName(destinationType, value); 
     Object enumValue = Enum.Parse(destinationType, name, false); 

     Console.WriteLine("" + value + " = " + enumValue); 
    } 
} 
+0

Ahi ... ho bisogno di smettere di cercare di rispondere a domande come questo prima ho avuto il mio caffè ... –

+0

vedo ora , Console.WriteLine si trova anche in un livello che non ha accesso al tipo di enum. Ho completamente frainteso. Cancellata la mia (stupida) risposta. – GvS

risposta

74

Enum.ToObject(.... è quello che stai cercando!

C#

StringComparison enumValue = (StringComparison)Enum.ToObject(typeof(StringComparison), 5); 

VB.NET

Dim enumValue As StringComparison = CType([Enum].ToObject(GetType(StringComparison), 5), StringComparison) 

Se si fanno un sacco di Enum conversione provare a utilizzare la seguente classe che vi farà risparmiare un sacco di codice.

public class Enum<EnumType> where EnumType : struct, IConvertible 
{ 

    /// <summary> 
    /// Retrieves an array of the values of the constants in a specified enumeration. 
    /// </summary> 
    /// <returns></returns> 
    /// <remarks></remarks> 
    public static EnumType[] GetValues() 
    { 
     return (EnumType[])Enum.GetValues(typeof(EnumType)); 
    } 

    /// <summary> 
    /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. 
    /// </summary> 
    /// <param name="name"></param> 
    /// <returns></returns> 
    /// <remarks></remarks> 
    public static EnumType Parse(string name) 
    { 
     return (EnumType)Enum.Parse(typeof(EnumType), name); 
    } 

    /// <summary> 
    /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. 
    /// </summary> 
    /// <param name="name"></param> 
    /// <param name="ignoreCase"></param> 
    /// <returns></returns> 
    /// <remarks></remarks> 
    public static EnumType Parse(string name, bool ignoreCase) 
    { 
     return (EnumType)Enum.Parse(typeof(EnumType), name, ignoreCase); 
    } 

    /// <summary> 
    /// Converts the specified object with an integer value to an enumeration member. 
    /// </summary> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    /// <remarks></remarks> 
    public static EnumType ToObject(object value) 
    { 
     return (EnumType)Enum.ToObject(typeof(EnumType), value); 
    } 
} 

Ora, invece di scrivere (StringComparison)Enum.ToObject(typeof(StringComparison), 5); si può semplicemente scrivere Enum<StringComparison>.ToObject(5);.

+1

Questo è esattamente quello che stavo cercando, grazie! –

+3

Legenda! Non lo sapevo. Non è lo stackoverflow brillante ?! :-) –

+1

beh non so leggenda ma grazie: P – Peter

0

Sulla base della @ risposta di Pietro qui è il metodo per Nullable<int> a Enum conversione:

public static class EnumUtils 
{ 
     public static bool TryParse<TEnum>(int? value, out TEnum result) 
      where TEnum: struct, IConvertible 
     { 
      if(!value.HasValue || !Enum.IsDefined(typeof(TEnum), value)){ 
       result = default(TEnum); 
       return false; 
      } 
      result = (TEnum)Enum.ToObject(typeof(TEnum), value); 
      return true; 
     } 
} 

Utilizzando EnumUtils.TryParse<YourEnumType>(someNumber, out result) diventa utile per molti scenari. Ad esempio, WebApi Controller in Asp.NET non ha una protezione predefinita contro parametri Enum non validi. Asp.NET utilizzerà solo il valore default(YourEnumType), anche se alcuni passaggi null, -1000, 500000, "garbage string" o ignorano totalmente il parametro. Inoltre, ModelState sarà valida in tutti questi casi, quindi una delle soluzioni è quella di utilizzare int? tipo con controllo personalizzato

public class MyApiController: Controller 
{ 
    [HttpGet] 
    public IActionResult Get(int? myEnumParam){  
     MyEnumType myEnumParamParsed; 
     if(!EnumUtils.TryParse<MyEnumType>(myEnumParam, out myEnumParamParsed)){ 
      return BadRequest($"Error: parameter '{nameof(myEnumParam)}' is not specified or incorrect"); 
     }  

     return this.Get(washingServiceTypeParsed);    
    } 
    private IActionResult Get(MyEnumType myEnumParam){ 
     // here we can guarantee that myEnumParam is valid 
    } 
0

Se si archiviano un Enum in un DataTable, ma non si sa quale colonna è un enum e che è una stringa/int, è possibile accedere al valore in questo modo:

foreach (DataRow dataRow in myDataTable.Rows) 
{ 
    Trace.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); 
    foreach (DataColumn dataCol in myDataTable.Columns) 
    { 
     object v = dataRow[dataCol]; 
     Type t = dataCol.DataType; 
     bool e = false; 
     if (t.IsEnum) e = true; 

     Trace.WriteLine((dataCol.ColumnName + ":").PadRight(30) + 
      (e ? Enum.ToObject(t, v) : v)); 
    } 
} 
Problemi correlati