Domanda

ho ottenuto un valore Int16, dal database, e la necessità di convertire questo in un tipo enum. Questo è, purtroppo, avviene in uno strato di codice che conosce molto poco circa gli oggetti ad eccezione di quello che può raccogliere attraverso la riflessione.

In quanto tale, esso finisce per chiamare Convert.ChangeType che non riesce con un'eccezione getto valido.

Ho trovato quello che considero un workaround 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 stringa?

Ecco un 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);
    }
}
È stato utile?

Soluzione

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 provare la conversione mediante 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);.

Altri suggerimenti

In base alla @ 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 Asp.NET non ha la protezione in contumacia contro params Enum non validi. Asp.NET sarà solo utilizzare default(YourEnumType) valore, anche se alcuni passaggi null, -1000, 500000, "garbage string" o totalmente ignora 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
    }

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));
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top