Repurposing Enumerations
page 2 of 2
by Mathew Nolton
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 14853/ 25
Article Contents:

Part 2

TypeConverters
TypeConverters are the answer, specifically a derivation of TypeConverter called EnumConverter. By deriving from EnumConverter we can change how an enumeration is converted to and from a string value. Furthermore, through the use of attribute-based programming, we can assign the converter to our newly defined enumeration so that at runtime we can query for the TypeConverter class and then convert the enumeration value on the fly. Slick? You bet!

 

Defining the Enumeration

Notice the TypeConverter(typeof(TaskCodeConverter))] attribute.

/*

** Here we are defining our enumeration that we will expose to the

** outside world. We are using the TypeConverterAttribute to assign

** our Converter to this enumeration e.g.

** [TypeConverter(typeof(TaskCodeConverter))]. This enables

** us to query for it at runtime so that we can convert values

** on the fly.

*/

[TypeConverter(typeof(TaskCodeConverter))]

public enum eTaskCode

{

      ChangeOfServiceSendTechnician,

      ChangeOfServiceNoTechnician,

      InstallServiceSendTechnician,

      InstallServiceNoTechnician,

}

 

Defining the Custom EnumConverter

// This is our TypeConverter class. Notice that we are deriving

// from EnumConverter

public class TaskCodeConverter : EnumConverter

{

      // Here we are defining the values that the API expect.

      // Note: public read-only constants are still a great way

      // of exposing a strict set of valid values. I just don’t

      // want to expose them to users of my webservices or

      // my businesslogic layer.

      #region constants

      public const string CSRVN="CSRVN";

      public const string CSRVY="CSRVY";

      public const string INSTN="INSTN";

      public const string INSTY="INSTY";

      #endregion constants

 

      #region ctors

      // The default constructor (define the enum this class supports).

      public TaskCodeConverter ():base(typeof(eTaskCode)){}

      #endregion ctors

 

      #region public methods

      // This OVERRIDDEN method handles converting “From” a specific

      // type. We only care about string values, so we are only handling

      // string types. Any other type is passed up to the base type

      // EnumConverter.

      // This method is all about converting TO our Enumeration

      // eTaskCode. Nothing else should ever be returned.

      public override object ConvertFrom(ITypeDescriptorContext

          context,system.Globalization.CultureInfo culture,

          object value)

      {

         // remember we only care about strings…………

         if(value as string != null)

         {

            // it’s a good idea to clean up the string…………

            string localTask=((string)value).Trim().ToUpper();

            // If they pass us nothing, then throw an exception.

            if(localTask.Length == 0)

            {

                  throw new ArgumentNullException("taskCode");

            }

            else

            {

                  // compare what we got with out constants defined above.

                  // only handle defined values.

                  switch(localTask)

                  {

                        case CSRVN:

                           return eTaskCode.ChangeOfServiceSendTechnician;

                        case CSRVY:

                           return eTaskCode.ChangeOfServiceNoTechnician;

                        case INSTN:

                           return eTaskCode.InstallServiceSendTechnician;

                        case INSTY:

                           return eTaskCode.InstallServiceNoTechnician;

                        default:

                           throw new ArgumentException(string.Format("Invalid

                              taskCode value: {0}",localTask));

                  }

            }

         }

         else

         {

            // all other types get passed up to the base class EnumConverter.

            return base.ConvertFrom(context,culture,value);

         }

      }

      // This OVERRIDDEN method handles converting “To” a specific

      // type. We only care about string values, so we are only handling

      // string types. Any other type is passed up to the base type

      // EnumConverter.

      // This method is all about converting FROM our Enumeration eTaskCode

      // to a value of a specified type. Since we want to return a value

      // that the API understands then that is what we return.

      public override object ConvertTo(ITypeDescriptorContext context,

            System.Globalization.CultureInfo culture, object value,

            Type destinationType)

      {

            // check if we are returning a string.

            if(destinationType==typeof(string))

            {

                  switch((eTaskCode)value)

                  {

                        case eTaskCode.ChangeOfServiceSendTechnician:

                              return CSRVN;

                        case eTaskCode.ChangeOfServiceNoTechnician:

                              return CSRVY;

                        case eTaskCode.InstallServiceSendTechnician:

                              return INSTN;

                        default:

                              return INSTY;

                  }

            }

            else

            {

                  return base.ConvertTo(context,culture,value,destinationType);

            }

      }

      #endregion public methods

}

 

Example in Action

// Notice that we are using the enumeration.

public double CreateWorkOrder(eTaskCode taskCode,

                              string accountNumber)

{

    ...

   string task = (string)TypeDescriptor.GetConverter(typeof(

      eTaskCode)).ConvertTo(taskCode,typeof(string));

   // task will now contain CSRVN,CSRVY,INSTN or INSTY

    ...

}

 

Conversely, to convert a string value to an eTaskCode value, you can do this.

eTaskCode taskCode = (eTaskCode)TypeDescriptor.GetConverter(typeof(

                         eTaskCode)).ConvertFrom(“CSRVN”);

 

// taskCode will be equal to eTaskCode.ChangeOfServiceSendTechnician

 

Conclusion

This article covered using enumerations and a custom EnumConverter class to handle conversions to and from a set of discrete string values. This approach has a number of advantages and can be used in a number of situations. We find it especially useful when presented with the problem of creating a façade over a third-party API. Some other aspects are:

  • It plugs directly into the .NET Framework and leverages conversion functionality designed into .NET for this purpose.
  • It localizes all conversion code for an enumeration to a single class.
  • Using TypeConverterAttribute(), you can assign your converter class at design time to your enumeration, so that you can retrieve and use it at runtime.

View Entire Article

User Comments

Title: Repurposing Enumerations - a different approach   
Name: Matteo
Date: 2008-01-14 7:22:24 AM
Comment:
Hello,

I came to this article months ago when I had to manage a similar situation.
It was very helpful for me, mainly for letting me know about TypeConverter and
EnumConverter.
It drove me in the right direction, though I chose a different approach.
I wanted to keep client code as simple as possible:

1. MyObject.Property = MyEnum.Item;
2. string humanReadable = MyObject.Property;

still being able to store in 'humanReadable' something different from the default string
representation of enum items.

I implemented a little helper class with a couple of conversion operators.
I published a description of my approach in my blog at the following URL:

http://ilmatte.wordpress.com/2008/01/12/string-representation-of-enums/

and I would like you to visit and comment it if you can.

Thank you very much.

Matteo






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2021 ASPAlliance.com  |  Page Processed at 2021-02-26 1:36:47 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search