TypeConverters: There's not enough TypeDescripter.GetConverter in the world
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.
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]
-
Define a class that derives from TypeConverter.
-
Override the CanConvertFrom method that specifies which type the converter can convert from. This method is overloaded.
-
Override the ConvertFrom method that implements the conversion. This method is overloaded.
-
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.
-
Override the ConvertTo method that implements the conversion. This method is overloaded.
-
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.
About Newsletter
http://jfoscoding.blogspot.com/2007/11/easy-mistake-using-typeconverter.html
Dragan - Thanks! My source code formatter is wonky for generics. I'll fix it tonight.
thank you .it saved me a lot of time and increased my knowledges.
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.
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!
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.
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.
Comments are closed.
It seems that your source code is reformatted: references to generic types <bool> and <t> are formatted like html tags, wit closing tags...