Question

Est-ce que quelqu'un sait comment transformer une valeur enum en une valeur lisible par l'homme ?

Par exemple:

ThisIsValueA devrait être « Ceci est la valeur A ».

Était-ce utile?

La solution

En convertissant ceci à partir d'un extrait de code VB qu'un certain Ian Horwill a laissé à un article de blog il y a longtemps...Depuis, je l'ai utilisé avec succès en production.

    /// <summary>
    /// Add spaces to separate the capitalized words in the string, 
    /// i.e. insert a space before each uppercase letter that is 
    /// either preceded by a lowercase letter or followed by a 
    /// lowercase letter (but not for the first char in string). 
    /// This keeps groups of uppercase letters - e.g. acronyms - together.
    /// </summary>
    /// <param name="pascalCaseString">A string in PascalCase</param>
    /// <returns></returns>
    public static string Wordify(string pascalCaseString)
    {            
        Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
        return r.Replace(pascalCaseString, " ${x}");
    }

(nécessite « en utilisant System.Text.RegularExpressions ; »)

Ainsi:

Console.WriteLine(Wordify(ThisIsValueA.ToString()));

Retournerais,

"This Is Value A".

C'est beaucoup plus simple et moins redondant que de fournir des attributs Description.

Les attributs ne sont utiles ici que si vous devez fournir une couche d'indirection (ce que la question n'a pas demandé).

Autres conseils

Le .ToString sur Enums est relativement lent en C#, comparable à GetType().Name (il pourrait même l'utiliser sous les couvertures).

Si votre solution doit être très rapide ou très efficace, il est préférable de mettre vos conversions en cache dans un dictionnaire statique et de les rechercher à partir de là.


Une petite adaptation du code de @Leon pour profiter de C#3.Cela a du sens en tant qu'extension des énumérations - vous pouvez limiter cela au type spécifique si vous ne voulez pas les encombrer toutes.

public static string Wordify(this Enum input)
{            
    Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
    return r.Replace( input.ToString() , " ${x}");
}

//then your calling syntax is down to:
MyEnum.ThisIsA.Wordify();

La plupart des exemples que j'ai vus impliquent le marquage de vos valeurs d'énumération avec les attributs [Description] et l'utilisation de la réflexion pour effectuer la "conversion" entre la valeur et la description.Voici un ancien article de blog à ce sujet :

http://geekswithblogs.net/rakker/archive/2006/05/19/78952.aspx

Vous pouvez hériter de la classe « Attribute » de System.Reflection pour créer votre propre classe « Description ».Comme ça (de ici):

using System;
using System.Reflection;
namespace FunWithEnum
{
    enum Coolness : byte
    {
        [Description("Not so cool")]
        NotSoCool = 5,
        Cool, // since description same as ToString no attr are used
        [Description("Very cool")]
        VeryCool = NotSoCool + 7,
        [Description("Super cool")]
        SuperCool
    }
    class Description : Attribute
    {
        public string Text;
        public Description(string text)
        {
            Text = text;
        }
    }
    class Program
    {
        static string GetDescription(Enum en)
        {
            Type type = en.GetType();
            MemberInfo[] memInfo = type.GetMember(en.ToString());
            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);
                if (attrs != null && attrs.Length > 0)
                    return ((Description)attrs[0]).Text;
            }
            return en.ToString();
        }
        static void Main(string[] args)
        {
            Coolness coolType1 = Coolness.Cool;
            Coolness coolType2 = Coolness.NotSoCool;
            Console.WriteLine(GetDescription(coolType1));
            Console.WriteLine(GetDescription(coolType2));
        }
    }
}

Vous pouvez également consulter cet article : http://www.codeproject.com/KB/cs/enumdatabinding.aspx

Il s'agit spécifiquement de la liaison de données, mais montre comment utiliser un attribut pour décorer les valeurs d'énumération et fournit une méthode "GetDescription" pour récupérer le texte de l'attribut.Le problème avec l'utilisation de l'attribut de description intégré est qu'il existe d'autres utilisations/utilisateurs de cet attribut, il est donc possible que la description apparaisse là où vous ne le souhaitez pas.L'attribut personnalisé résout ce problème.

J'ai trouvé préférable de définir vos valeurs d'énumération avec un score inférieur afin que ThisIsValueA soit This_Is_Value_A, alors vous pouvez simplement faire un enumValue.toString().Replace("_"," ") où enumValue est votre variable.

Une alternative à l'ajout Description Les attributs de chaque énumération consistent à créer une méthode d'extension.Pour réutiliser l'énumération "Coolness" d'Adam :

public enum Coolness
{
    NotSoCool,
    Cool,
    VeryCool,
    SuperCool
}

public static class CoolnessExtensions
{
    public static string ToString(this Coolness coolness)
    {
        switch (coolness)
        {
            case Coolness.NotSoCool:
                return "Not so cool";
            case Coolness.Cool:
                return "Cool";
            case Coolness.VeryCool:
                return "Very cool";
            case Coolness.SuperCool:
                return Properties.Settings.Default["SuperCoolDescription"].ToString();
            default:
                throw new ArgumentException("Unknown amount of coolness", nameof(coolness));
        }
    }
}

Bien que cela signifie que les descriptions sont plus éloignées des valeurs réelles, cela vous permet d'utiliser la localisation pour imprimer des chaînes différentes pour chaque langue, comme dans mon VeryCool exemple.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top