snippetcsharpMinor
Is this a good/safe way to convert enums?
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:
Originally, I decided on writing the same method for them, over and over again:
Then it occurred to me that I could make one private method to do this:
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.
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:
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:
Source for the method to retrieve your DisplayName objects
You can roll this into a more complete generic method too:
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.
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.