|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionYou may not have written yet your own type converter. But any time you developed a web form or Windows form using the Visual Studio .NET designer or used the view state architecture of ASP.NET you have relied 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 an integer to a string. The .NET framework comes with a number of type converters which perform all that work for you for the most common .NET types. But when you create your own complex types then 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 which 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 can also 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 can also 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 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 which uses reflection. Provide your own type converter. You can not store complex types in state view unless it is marked serializable or has its own type converter associated. How do type converters work?Type converters allow you to convert from your type to another type and also form another type back to your type. All type converters are inherited from the
Walk through a sample type converterThe attached sample application defines three complex types - The following code snippet shows the implementation of 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 If the value is a public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
// if no value passed along then return a new Latitute instance
if (value == null)
return new Latitude();
// if the source is a string then convert to our type
if (value is string)
{
// get strongly typed value
string StringValue = value as string;
// if empty string then return again 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 we need
TypeConverter IntConverter =
TypeDescriptor.GetConverter(typeof(int));
// get the degrees, minutes and seconds value
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);
}
This is all we need to convert from a public override bool CanConvertTo(ITypeDescriptorContext context,
Type destinationType)
{
if ((destinationType == typeof(string)) |
(destinationType == typeof(InstanceDescriptor)))
return true;
else
return base.CanConvertTo(context, destinationType);
}
The final code snippet shows the implementation of the If the destination type is an instance descriptor then we perform the following processing. If the value is public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
// check that the value passed along is of our type
if (value != null)
if (!(value is Latitude))
throw new Exception(WrongType);
// convert to a string
if (destinationType == typeof(string))
{
// no Latitude instance so we return an empty string
if (value == null)
return String.Empty;
// get strongly type value
Latitude LValue = value as Latitude;
// get the type converters we need
TypeConverter IntConverter =
TypeDescriptor.GetConverter(typeof(Int32));
TypeConverter EnumConverter =
TypeDescriptor.GetConverter(typeof(LatitudeDiretcion));
// return string representation of Latitude
return IntConverter.ConvertToString(context, culture, LValue.Degrees) +
EnumConverter.ConvertToString(context,culture,
LValue.Direction).Substring(0,1) +
IntConverter.ConvertToString(context, culture,
LValue.Minutes) + MinutesUnit +
IntConverter.ConvertToString(context, culture,
LValue.Seconds) + SecondsUnit;
}
// convert to a instance descriptor
if (destinationType == typeof(InstanceDescriptor))
{
// no Latitude instance
if (value == null)
return null;
// get strongly type value
Latitude LatitudeValue = value as Latitude;
// used to describe the constructor
MemberInfo Member = null;
object[] Arguments = null;
// get the constructor of our Latitude type
Member =
typeof(Latitude).GetConstructor(new Type[] { typeof(int),
typeof(int), typeof(int), typeof(LatitudeDiretcion) });
// the arguments to pass along to the Latitude constructor
Arguments = new object[] {
LatitudeValue.Degrees, LatitudeValue.Minutes,
LatitudeValue.Seconds, LatitudeValue.Direction };
// return instance descriptor or null if we could not
// find a constructor
if (Member != null)
return new InstanceDescriptor(Member, Arguments);
else
return null;
}
// call base converter to convert
return base.ConvertTo(context, culture, value, destinationType);
}
That is all you need to do for your custom type converter. You can assign your type converter to your type by applying the [TypeConverter(typeof(LatitudeTypeConverter))]
public class Latitude
{
public override string ToString()
{
return ToString(CultureInfo.InvariantCulture);
}
public string ToString(CultureInfo Culture)
{
return TypeDescriptor.GetConverter(GetType()).ConvertToString(null,
Culture, this);
}
}
We also implement the Please see the attached sample application which shows the implementation of the The standard .NET type convertersAs mentioned the .NET framework comes with a number of standard type converters you can leverage (MSDN help topic ). You for example find a You can also use classes with properties in the designer and property browser by simply applying the [TypeConverter(typeof(GPSLocationTypeConverter))]
public class GPSLocation
{
The <ui:LocationControl ID="LocationControl1" runat="server"
Location-GPSLatitude="12N1'2"" Location-GPSLongitude="24W3'4"">
</ui:LocationControl>
By using the <ui:LocationControl ID="LocationControl1" runat="server">
<Location GPSLatitude="12N1'3"" GPSLongitude="24W3'4"" />
</ui:LocationControl>
There are many more control attributes you can apply. But that goes beyond this article. Here is the code snippet for the [DefaultProperty("GPSLocation")]
[ParseChildren(true)]
[ToolboxData("<{0}:LocationControl runat="server">")]
public class LocationControl : WebControl
{
Please see the attached sample for a complete working control. It allows you to set the value of the GPS location property in the property browser and then outputs it when rendering the control. SummaryType converters are an important part of the Visual Studio .NET designer and property browser as well as the view state management. As long as you use standard types there is no need to write your own type converter. But when you create your own complex types you need to implement your own type converters. This article explains how to implement your own type converters and how to associate those type converters with your complex types. The .NET framework makes it very easy to implement your own type converters by inheriting from the
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||