Type Converters, Your Friendly Helpers!

Introduction

You may not have written your own type converter yet. But, any time you develop a Web form or Windows form using the Visual Studio .NET designer or use the view state architecture of ASP.NET, you rely on the help of a type converter. As the name already states, type converters are used to convert from one type to another; for example, from an integer to a string. The .NET framework comes with a number of type converters that perform all that work for you for with the most common .NET types. But, when you create your own complex types, you need to create your own type converters. This article will explain how you can write your own type converter and then assign that to your own type.

Where Are Type Converters Used?

Type converters are mostly used to convert your type to a string or a string back to your type. Web controls and Web forms have properties that you can view and edit through the property browser of the Visual Studio .NET designer. The property browser finds the type of the property and then the type converter associated with that type to convert the type to a string. Any changes the user makes to the property in the property browser is written back to the property, which again uses the type converter to convert from a string back to the type.

You also can design Web forms through the Visual Studio .NET designer. This allows you to place new controls onto the Web form and modify their properties. The designer creates the necessary form tags and properties. You also can switch to the “source mode” and then edit the tags itself. You can add new properties to a control or modify existing ones. This is called “declarative persistence.” The designer itself uses again type converters to convert a property from your type to a string and again from a string back to your type.

The state view framework provided by Web controls and Web forms also relies on type converters. Type converters provide a better performance than reflection. So, whenever possible, avoid binary serialization that uses reflection. Provide your own type converter. You cannot store complex types in state view unless they are marked serializable or have their own type converter associated.

How Do Type Converters Work?

Type converters allow you to convert from your type to another type and also from another type back to your type. All type converters are inherited from the TypeConverter base class provided by .NET. You need to overwrite four methods. The methods CanConvertTo and ConvertTo are used when converting from your type to another type; for example, to a string. The methods CanConvertFrom and ConvertFrom are used when converting from another type back to your type; for example, from a string.

  • CanConvertTo—Passes along the required destination type; for example, the type of the string. The method returns true if it can convert to that type; otherwise, false.
  • ConvertTo—Gets passed along the type to convert, the destination type, and the culture info to use during the type conversion. This method then returns the converted type.
  • CanConvertFrom—Passes along the source type; for example, the type the of string. The method returns true if it can convert from that type back to your type. Otherwise, it returns false.
  • ConvertFrom—Gets passed along the type to convert from and the culture info to use during the type conversion. This then method returns the converted type.

Walk Through a Sample Type Converter

The attached sample application defines three complex types—GPSLocation, Latitude, and Longitude. As the names already indicate, these types are used to describe a GPS position. Each type has its own type converter associated with it. Now, you will walk through the LatitudeTypeConverter.

The following code snippet shows the implementation of CanConvertFrom. This type converter will be able to convert from a string back to a Latitude type. So, if the source type is of the string type, you return true; otherwise, you call the method of the base class—the TypeConverter class.

public override bool CanConvertFrom(ITypeDescriptorContext context,
                                    Type sourceType)
{
   if (sourceType == typeof(string))
      return true;
   else
      return base.CanConvertFrom(context, sourceType);
}

The next code snippet shows the implementation of the ConvertFrom method. First, check whether the value (type) passed along is null. In that case, create a new instance of the Latitude class and return it. This means no value was provided, so you create an empty instance of your type. Next, check whether the value passed along is of the string type. In that case, you will process the request; otherwise, again call the method of the base class. So, you perform a conversion from a string but any other conversion is delegated to the base class.

If the value is a string, you check the length. If the length is zero or less, you again return a new instance of the Latitude class. This again means that no value provided, so you create an empty instance of your type. Now, you can start with the actual conversion. The Latitude type consists of a degree, latitude direction (North or South), and the minutes and seconds; for example, 48N15’0″ for Vienna (Austria). First, you search for the North direction and, if not found, you search for the South direction. Finally, you search for the minute character and second character. Next, you check that you have found a latitude direction, minute character, and second character. You also check that you have a degree value by making sure that the latitude direction starts at a position greater then zero. If any of them is missing, you throw an appropriate exception informing the caller that the format is not correct. Next, you get an instance of the integer type converter by calling TypeDescriptor.GetConverter(typeof(int)). This returns the type converter that can be used to convert to or from an integer. Finally, you cut the value string apart to obtain the degrees, minutes, and seconds and use the integer converter to convert each from a string to an integer. Last thing, you again create a new instance of the Latitude class and pass along the four values—latitude direction, degrees, minutes, and seconds. This is the converted type you return.

public override object ConvertFrom(ITypeDescriptorContext context,
                                   System.Globalization.CultureInfo
                                   culture, object value)
{
   // if no value passed along, return a new Latitute instance
   if (value == null)
      return new Latitude();

   // if the source is a string, convert to your type
   if (value is string)
   {
      // get strongly typed value
      string StringValue = value as string;

      // if empty string, again return a new instance of Latitude
      if (StringValue.Length <= 0)
         return new Latitude();

      // search of the North latitude key
      int DirPos =
         StringValue.IndexOf(LatitudeDiretcion.North.ToString().
         Substring(0,1));
      LatitudeDiretcion Direction = LatitudeDiretcion.North;

      // if not found, search for the South latitude key
      if (DirPos == -1)
      {
         DirPos = StringValue.IndexOf(LatitudeDiretcion.South.
                  ToString().Substring(0, 1));
         Direction = LatitudeDiretcion.South;
      }

      // get the position of the seconds and minutes unit character
      int MinutesPos = StringValue.IndexOf(MinutesUnit);
      int SecondsPos = StringValue.IndexOf(SecondsUnit);

      // the minutes are missing
      if (MinutesPos == -1)
         throw new Exception(NoMinutes);

      // the seconds are missing
      if (SecondsPos == -1)
         throw new Exception(NoSeconds);

      // the Latitude direction is missing
      if (DirPos == -1)
         throw new Exception(NoDirection);

      // the degrees are missing
      if (DirPos == 0)
         throw new Exception(NoDegrees);

      // get the type converters you need
      TypeConverter IntConverter =
         TypeDescriptor.GetConverter(typeof(int));

      // get the degrees, minutes, and seconds values
      int Degrees = (int)IntConverter.ConvertFromString(context,
                     culture, StringValue.Substring(0, DirPos));

      int Minutes = (int)IntConverter.ConvertFromString(context,
                     culture, StringValue.Substring(DirPos + 1,
                     MinutesPos - DirPos - 1));

      int Seconds = (int)IntConverter.ConvertFromString(context,
                     culture, StringValue.Substring(MinutesPos + 1,
                     SecondsPos - MinutesPos - 1));

      // create a new Latitude instance with these values and return it
      return new Latitude(Degrees, Minutes, Seconds, Direction);
   }

   // otherwise, call the base converter
   else
      return base.ConvertFrom(context, culture, value);
}

More by Author

Must Read