Scott Hanselman

TypeConverters: There's not enough TypeDescripter.GetConverter in the world

May 10, '08 Comments [12] Posted in Source Code
Sponsored By

While reading source today, I saw some code in the wild today that looked roughly like this (not the actual code):

type = typeof(T);
if (type == typeof(Boolean))
{
returnValue = (T)((object)Convert.ToBoolean(value));
}
else if (type == typeof(String))
{
returnValue = (T)((object)value);
}
else if (type == typeof(Int16))
{
returnValue = (T)((object)Convert.ToInt16(value));
}
else if (type == typeof(Int32))
{
returnValue = (T)((object)Convert.ToInt32(value));
}
//...and on and on for a dozen+ types

You get the idea. This isn't that uncommon, I've seen it more of than not. The person who is writing it usually knows it's bad 50% of the time, but it's always a trade-off between figuring out the right search query (a tough one, in this case!) and knowing what to look for in MSDN.

This brings up one of my favorite classes in the BCL, the TypeDescriptor class. A method like this:

public static T GetTfromString<T>(string mystring)
{
var foo = TypeDescriptor.GetConverter(typeof(T));
return (T)(foo.ConvertFromInvariantString(mystring));
}

...would allow all that switch/if/else to go away replaced by:

bool b = GetTfromString("true");

You'd probably want to expand the method with checks to see if T was in fact, System.Type, or System.String, but you get the idea.

image There are lots of standard converters like EnumConvertor, ColorConvertor, and more, all waiting for you in System.ComponentModel as seen in the image at right.

Not only that, but you can make your own TypeConverters and spread the love. They are used extensively when displaying types in Property Grids, in WinForms, or in XAML. You can also use them in PowerShell as a better way to present your objects as strings when "casting" in PowerShell.

Jesse Liberty has a fine example showing how to use Type Convertors in Silverlight to enable you to put complex types in XAML attributes.

From MSDN:

To implement a simple type converter that can translate a string to a [Type]

  1. Define a class that derives from TypeConverter.

  2. Override the CanConvertFrom method that specifies which type the converter can convert from. This method is overloaded.

  3. Override the ConvertFrom method that implements the conversion. This method is overloaded.

  4. Override the CanConvertTo method that specifies which type the converter can convert to. It is not necessary to override this method for conversion to a string type. This method is overloaded.

  5. Override the ConvertTo method that implements the conversion. This method is overloaded.

  6. Override the IsValid method that performs validation. This method is overloaded.

That's it, and when that Type was decorated with an attribute like:

[TypeConverter(typeof(MyNewTypeConverter))]

Then that new TypeConverter would be picked up and used by the line of code I showed before. Much better than a switch or pile of if/elses, I think.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Saturday, May 10, 2008 11:40:16 AM UTC
Scott...
It seems that your source code is reformatted: references to generic types <bool> and <t> are formatted like html tags, wit closing tags...
Saturday, May 10, 2008 1:47:05 PM UTC
You can actually just use Convert.ChangeType("false", typeof(bool)); to convert a string to a bool. No custom type converter necessary.
Saturday, May 10, 2008 2:34:29 PM UTC
We use type convertors extensively in our config classes to ensure that the pesky strings in the config files will be converted to the actual types like Regex or Color, when they enter the process. Much cleaner for me, that playing with X(tra)ML
Saturday, May 10, 2008 7:07:49 PM UTC
Here's some more useful information about the most accurate way to use typeconverters (prettymuch what you said here plus one thing)
http://jfoscoding.blogspot.com/2007/11/easy-mistake-using-typeconverter.html
Saturday, May 10, 2008 7:40:45 PM UTC
Eric - Does that work with types that DO have custom converters? Does it work for typeof T?

Dragan - Thanks! My source code formatter is wonky for generics. I'll fix it tonight.
Monday, May 12, 2008 4:21:18 AM UTC
that was a cool and hard article but it worths reading and more.
thank you .it saved me a lot of time and increased my knowledges.
Monday, May 12, 2008 4:56:38 AM UTC
I have to admit that I don't really care for TypeConverters, though my experience with them has been with trying to do some fairly complicated things within Visual Studio to get my components to work the way I want them in the designer. I think they could have designed the type converters a little differently and perhaps separated out some of the other work the TypeConverters also do (such as getting a list of valid values).

This blog post motivated me into creating a blog post of my own. My article discusses three different methods of converting values (IConvertible, TypeConverters, and conversion methods) as well as provides a sample project that includes source code that is similar to System.Convert.ChangeType but can also handle TypeConverters and conversion methods. Here is the link to the article if you are interested - Type Conversions.
Monday, May 12, 2008 8:15:43 AM UTC
6. Override the IsValid method that performs validation. This method is overloaded.

Only too bad that most BCL TypeConverters don't do this correctly, for example, the GuidConverter's IsValid() will return true upon an empty string, or any invalid Guid string, but the GuidConverter.ConvertFromString() will throw a FormatException. See http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=96296. Otherwise very useful article!
WouterDemuynck
Monday, May 12, 2008 2:22:55 PM UTC
Thanks for brings this to attention, Scott! Coincidentally, it applied to something I was immediately work on and helped make my code more elegant and robust.
Wednesday, May 14, 2008 7:46:57 PM UTC
Unfortunately, converters are badly broken.
For example IsValid always returns true, DecimalConverter.FromString does not accept valid strings. See
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=329119
etc...
So, code similar to above is ugly, but necessary, workaround for a sloppy and buggy converters in .Net framework.
Tom
Tuesday, May 20, 2008 7:27:55 PM UTC
Scott, your source code formatter is really great looking, but it is broken in Opera.
Sebastien
Tuesday, May 20, 2008 7:33:49 PM UTC
Besides TypeConverter being slow and broken for some types, it also do not handle things such as trimming, DateTimeStyles, NumberStyles, default values, etc.

This is a good example of why having too many choices can be really bad. In the conversion case, There are a dozen way to convert stuff, but none of them "just work" (tm), we still need to roll our own.
Sebastien
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.