65.9K
CodeProject is changing. Read more.
Home

StringEnumerator

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.92/5 (6 votes)

Feb 2, 2007

3 min read

viewsIcon

40424

downloadIcon

248

A utility class relying on Generics and Attributes that allows strings to be enumerated (as enums)

Introduction

Ever wanted to treat strings like they were enumerations and put them through a switch statement? Ever wanted to bind the elements of an Enumeration to UI element but couldn't because the Enum names were not user friendly? How about storing a string as an Int in a database table and having that Int value strongly bound to a specific display string? The StringEnumerator utility class helps solve this problem by using Generics, Attributes, and Reflection to expose a set of static methods that transition between user friendly strings and Enum values.

Using the code

Of course, there's no real magic involved and C# doesn't intrinsically support string enumerators. The trick to achieving this effect is in the use of the DescriptionAttribute which we use to decorate the enumerator. The example below shows a Country enumeration with a few countries listed. The DescriptionAttribute is used to give the enum value a user friendly display name.

///<summary>
/// Test Enumerator that contains some countries.
///</summary>

public enumCountry
{
    [Description("United States")]
    UnitedStates,
    Canada,
    Mexico,

    [Description("United Kingdom")]
    UK,

    [Description("Virgin Islands")]
    VirginIslands,
}

Using the class is really simple as will be demonstrated in the code samples to follow. When converting from a string back to an enumeration, the Parse and TryParse methods will try to parse the passed in string to return the enumerator. The difference between the two methods is that Parse will throw and InvalidCastException if the string could not be parsed whereas TryParse returns a boolean flag that indicates if the operation was successful. Otherwise, both methods are identical in that they will first try to match the string to the enum value directly. If a match cannot be made then the methods will look for a DescriptionAttribute to match the string against. As illustrated in the example below, both "United States" and "United States" will return the Country.UnitedStates enum value.

//Match against the Description Attribute

string enumString = "United
States";

Country enumValue = StringEnumerator<Country>.Parse(enumString);

//Direct
match which is similar to Enum.Parse()

enumString = "UnitedStates";

enumValue = StringEnumerator<Country>.Parse(enumString);

// Try to parse the string.  Method will
// return false.

enumString = "United States of America";

success = StringEnumerator<Country>.TryParse(enumString,
            ref enumValue);

So the example above showed how to parse a string, now let's take a look at some of the methods that allow you to serialize an enumeration to a string or a collection. The StringEnumerator class provides a ToString method that will serialize an enumeration value to a string. This method will look for a DescriptionAttribute to return, and if one is not found, it will simply call built-in ToString method on the enum value to get the intrinsic behavior back to the user.

// In this case, ToString finds a [Description(..)] attribute 
// and returns the descriptive string back.

Country enumValue = Country.UnitedStates;
string expected = "United States";

string actual = StringEnumerator<Country>.ToString(enumValue);

Assert.AreEqual(expected, actual);

// In this case the ToString doesn't find a [Description] attribute and 
// returns the built-in string representation.

enumValue = Country.Canada;
expected = Country.Canada.ToString();
actual = StringEnumerator<Country>.ToString(enumValue);
Assert.AreEqual(expected, actual);

The static methods that return a collection work in a similar fashion to generate a collection of strings from a given enumeration. This technique can be used to bind an enumeration to a UI element.

// Generate a list of string from the enumerator to 
// populate a combobox

List<string>
enumValues = StringEnumerator<Country>.ToList();

comboBox.DataSource = enumValues;

Notes on Internationalization

Anybody who has had to internationalize (I18N) software below knows that hard-coding strings that are used for display purposes is not possible. Although, in its current state the StringEnumerator class does not support I18N, it could with some minor modifications be adapted to supply dynamic strings. One way to accomplish this would be to assign resource identifiers in the DescriptionAttribute in place of real strings. Then modify the parsing methods to lookup the real string value from a resource manager. This approach would then allow you to map integer values stored in a database to display values regardless of the local that the application is running within.