Monday, 10 June 2013

Enum operations for name value attributes

Enumerations are basically used to write clean and readable code for a set of constant values. I won’t be explaining about the basics of Enumeration but going to the next level we’ll see in this article how to manipulate the values, name and attributes using the Reflection at run time.

First let’s take a simple Enum. We’ll be using it through out the article for demo:

public enum TestEnum
{
[Description("Undefined Enum")]
Undefined = 0
[Description("Enumeration 1")]
Enum1 = 1,
[Description("Enumeration 2")]
Enum2 = 2,
}




Here are the list of operation with snippets that we can perform in order to use the TestEnum in various ways:


Get the name of Enum:


Console.WriteLine(TestEnum.Enum1.ToString());


Get the value of Enum:


Console.WriteLine(TestEnum.Enum1.ToString("d"));


The special thing you’ll see here is we have just mentioned the string formatter “d” and it’ll automatically fetch the value of Enum insteat of printing it’s name. So you don’t have to do explicit conversion like (int)TestEnum.Enum1 to get the value.


Get the description value on Enum: In our TestEnum we have provided some description over the Enum. So when required you can fetch the description attribute value if required. Below is the snippet for getting the value of description attribute using Reflection:


Snippet:


/// <summary>
/// Gets the error message attribute value.
/// </summary>
/// <param name="enumerationType">Type of the enumeration.</param>
/// <returns>
/// value of the attribute
/// </returns>
public static string GetDescriptionOfEnum(this Enum enumerationType)
{
Type type = enumerationType.GetType();

MemberInfo[] memInfo = type.GetMember(enumerationType.ToString());

if (memInfo.Length > 0)
{
object[] attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

if (attributes.Length > 0)
{
return ((DescriptionAttribute)attributes[0]).Description;
}
}

return enumerationType.ToString();
}
This snippet is an extension method that will search for the attribute and if it doesn’t find any then simply returning the name of the enumerationType.

 

Usage:

Console.WriteLine(TestEnum.Enum1.GetDescriptionOfEnum());


Get the Enum from string name: This is the case where you want to fetch the enum based on the String name provided for that Enum. for e.g. we have TestEnum.Enum1 is an enum and I want to get this by the string name “Enum1”. I’ve used reflection to get the name compare and return the Enum. Also additionally this snippet will also match the given string with attribute value on the enum and return the Enum if it matches. Here the code snippet for it.


Snippet:





public static TestEnum GetEnumByNameOrDescription(string parameterName)
{
var testEnum = TestEnum.Undefined;

foreach (string item in Enum.GetNames(typeof(TestEnum)))
{
testEnum =
string.Equals(item, parameterName, StringComparison.InvariantCultureIgnoreCase) ||
string.Equals(
((TestEnum)Enum.Parse(typeof(TestEnum), item, true)).GetDescriptionOfEnum(),
parameterName, StringComparison.InvariantCultureIgnoreCase)
? (TestEnum)Enum.Parse(typeof(TestEnum), item, true)
: TestEnum.Undefined;

if (testEnum != TestEnum.Undefined)
break;
}

if (testEnum == TestEnum.Undefined)
{
throw new Exception(
string.Format(
"Failed to cast string value {0} " +
"to enum type.",
parameterName));
}

return testEnum;
}

 

Usage:



// get enum by name
var enum1 = Extension.GetEnumByNameOrDescription("Enum1")
// get enum by description
var enum1 = Extension.GetEnumByNameOrDescription("Enumeration 1"))

 

Get Enum by value:

Let suppose you want to get the Enum by it’s value. for e.g. we have Enum2 with value 2. So if you want to get the Enum2 type by value 2 you can do it as shown in below example.

Snippet:

public static TestEnum GetEnumByValue(int value)
{
var testEnum = TestEnum.Undefined;

foreach (int item in Enum.GetValues(typeof(TestEnum)))
{
testEnum = item == value
? (TestEnum)Enum.Parse(typeof(TestEnum), value.ToString("d"), true)
: TestEnum.Undefined;

if(testEnum != TestEnum.Undefined)
break;
}

if (testEnum == TestEnum.Undefined)
{
throw new Exception(
string.Format(
"Failed to cast int value {0} " +
"to enum type.",
value));
}

return testEnum;
}


Usage:

var enum2 = Extension.GetEnumByValue(2);


The Extension is a static class I’ve created to keep these utility methods.

 

Here’s the complete code for the above article:

 


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
namespace Demo.EnumOperation
{
/// <summary>
/// The test Enum
/// </summary>
public enum TestEnum
{
[Description("Undefined Enum")]
Undefined = 0,
[Description("Enumeration 1")]
Enum1 = 1,
[Description("Enumeration 2")]
Enum2 = 2,
}

/// <summary>
/// Contains all the extension/utility method
/// </summary>
public static class Extension
{
public static TestEnum GetEnumByValue(int value)
{
var testEnum = TestEnum.Undefined;

foreach (int item in Enum.GetValues(typeof(TestEnum)))
{
testEnum = item == value
? (TestEnum)Enum.Parse(typeof(TestEnum), value.ToString("d"), true)
: TestEnum.Undefined;

if (testEnum != TestEnum.Undefined)
break;
}

if (testEnum == TestEnum.Undefined)
{
throw new Exception(
string.Format(
"Failed to cast int value {0} " +
"to enum type.",
value));
}

return testEnum;
}

public static TestEnum GetEnumByNameOrDescription(string parameterName)
{
var testEnum = TestEnum.Undefined;

foreach (string item in Enum.GetNames(typeof(TestEnum)))
{
testEnum =
string.Equals(item, parameterName, StringComparison.InvariantCultureIgnoreCase) ||
string.Equals(
((TestEnum)Enum.Parse(typeof(TestEnum), item, true)).GetDescriptionOfEnum(),
parameterName, StringComparison.InvariantCultureIgnoreCase)
? (TestEnum)Enum.Parse(typeof(TestEnum), item, true)
: TestEnum.Undefined;

if (testEnum != TestEnum.Undefined)
break;
}

if (testEnum == TestEnum.Undefined)
{
throw new Exception(
string.Format(
"Failed to cast string value {0} " +
"to enum type.",
parameterName));
}

return testEnum;
}

/// <summary>
/// Gets the error message attribute value.
/// </summary>
/// <param name="enumerationType">Type of the enumeration.</param>
/// <returns>
/// value of the attribute
/// </returns>
public static string GetDescriptionOfEnum(this Enum enumerationType)
{
Type type = enumerationType.GetType();

MemberInfo[] memInfo = type.GetMember(enumerationType.ToString());

if (memInfo.Length > 0)
{
object[] attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

if (attributes.Length > 0)
{
return ((DescriptionAttribute)attributes[0]).Description;
}
}

return enumerationType.ToString();
}
}

/// <summary>
/// Main program
/// </summary>
class EnumOperations
{
static void Main(string[] args)
{
var enum2 = Extension.GetEnumByValue(2);

var enum1 = Extension.GetEnumByNameOrDescription("Enum1");
var enumTest1 = Extension.GetEnumByNameOrDescription("Enumeration 1");
Console.WriteLine(Extension.GetEnumByNameOrDescription("Enum1").ToString("d"));
Console.WriteLine(TestEnum.Enum1.ToString("d"));
Console.WriteLine(TestEnum.Enum1.GetDescriptionOfEnum());

Console.ReadKey();
}
}
}