HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcsharpMinor

Is this a good/safe way to convert enums?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thisconvertwaysafegoodenums

Problem

Due to the fact that Entity does not support Enums, I am converting them to strings, string lists, and back again.

The reason is two fold:
type-safety, and consistency in the database.

Now, I have a bunch of these, but I will use Credit Cards as an example:

public enum CreditCardName
    {
        VISA,
        Master_Card,
        Discover,
        American_Express
    }


Originally, I decided on writing the same method for them, over and over again:

public static List GetCreditCardTypes()
    {
        var list = Enum.GetNames(typeof(CreditCardName));
        return list.Select(n => n.Replace("_", " ")).ToList();
    }


Then it occurred to me that I could make one private method to do this:

public static List GetCreditCardTypes()
    {
        return EnumToList(typeof(CreditCardName));
    }

    private static List EnumToList(Type type)
    {
        var list = Enum.GetNames(type);
        return list.Select(n => n.Replace("_", " ")).ToList();
    }


Now I'm also doing something similar in reverse, but will skip the code. The question I have is if this is a good way to go about this? I know there are other workarounds for Entity's lack of enum support, but they are a bit cumbersome for my simple needs. I have never used Types in this way, so I just wanted to check that this is how Type/typeof are intended to be used, and that this will not cause unforeseen runtime issues.

Solution

I solved a similar issue by inventing a DisplayName attribute, so I can define my enums like this:

public enum CreditCardName
{
    [DisplayName("VISA")]
    Visa,

    [DisplayName("MasterCard")]
    MasterCard,

    [DisplayName("Discover")]
    Discover,

    [DisplayName("American Express")]
    AmericanExpress
}


This has a number of advantages. For one, apps like Resharper will stop complaining about your naming scheme. Also, your string doesn't have to actually correspond to an English name, it could correspond to an entry in a translation strings file or something like that.

Source for DisplayName:

[AttributeUsage(AttributeTargets.Field)]
public class DisplayName : Attribute
{
    public string Title { get; private set; }

    public DisplayName(string title)
    {
        this.Title = title;
    }
}


Source for the method to retrieve your DisplayName objects

IEnumerable attributes = from attribute in typeof(CreditCardName).GetCustomAttributes(true)
                                              let displayName = attribute as DisplayName
                                              where displayName != null
                                              select displayName;


You can roll this into a more complete generic method too:

public string[] GetNames()
{
    return (from attribute in typeof(CreditCardName).GetCustomAttributes(true)
                                                     let displayName = attribute as DisplayName
                                                     where displayName != null
                                                     select displayName.Title).ToArray();
}


Unfortuately, I there isn't a way you can enforce that TEnum is an enum at compile time, but you could make it throw an exception instead.

Code Snippets

public enum CreditCardName
{
    [DisplayName("VISA")]
    Visa,

    [DisplayName("MasterCard")]
    MasterCard,

    [DisplayName("Discover")]
    Discover,

    [DisplayName("American Express")]
    AmericanExpress
}
[AttributeUsage(AttributeTargets.Field)]
public class DisplayName : Attribute
{
    public string Title { get; private set; }

    public DisplayName(string title)
    {
        this.Title = title;
    }
}
IEnumerable<DisplayName> attributes = from attribute in typeof(CreditCardName).GetCustomAttributes(true)
                                              let displayName = attribute as DisplayName
                                              where displayName != null
                                              select displayName;
public string[] GetNames<TEnum>()
{
    return (from attribute in typeof(CreditCardName).GetCustomAttributes(true)
                                                     let displayName = attribute as DisplayName
                                                     where displayName != null
                                                     select displayName.Title).ToArray();
}

Context

StackExchange Code Review Q#3337, answer score: 9

Revisions (0)

No revisions yet.