There are situations when one needs to convert the string values to ValueTypes(int, guid, datetime, Enums, Nullables etc.). A situation of doing these conversion could be to read Settings store in Configuration file or in database and converting them to their respective value type. I have seen people have writing if..else ladder to match the type and use the specific TypeConverter method from static class i.e. Convert.To<ValueType>();
Here’s a sample what was observed
- public object ConvertToValueType(string value, Type targetType)
- {
- object result = null;
-
- bool isEmpty = string.IsNullOrWhiteSpace(value);
-
- if (targetType == typeof (string))
- {
- result = value;
- }
- else if (targetType == typeof (Int32) || targetType == typeof (int))
- {
- if (isEmpty)
- {
- result = 0;
- }
- else
- {
- result = Int32.Parse(value);
- }
- }
- else if (targetType == typeof (Guid))
- {
- if (isEmpty)
- {
- result = Guid.Empty;
- }
- else
- {
- result = new Guid(value);
- }
- }
- else if (targetType.IsEnum)
- {
- result = Enum.Parse(targetType, value);
- }
- else if (targetType == typeof (byte[]))
- {
- result = Convert.FromBase64String(value);
- }
- else if (targetType == typeof (DateTime))
- {
- if (isEmpty)
- {
- result = DateTime.MinValue;
- }
- else
- {
- result = Convert.ToDateTime(value);
- }
- }
-
- return result;
- }
This solution would work and I can easily tell many of you have seen or done things like this, but look at this again. There will be an IF…Else condition for each type in the system.
The problem can be solved by using a System class
System.ComponentModel.TypeDescriptor that provide underlying information of a Type. So the above complex statement chain for Conversion can be converted to something like this using an extension method accepting generic types:
- private static bool TryConvertTo<T>(this string value, out object result)
- {
- var newType = typeof(T);
- result = default(T);
- if (string.IsNullOrWhiteSpace(value))
- {
-
- return true;
- }
-
- try
- {
- var converter = TypeDescriptor.GetConverter(typeof(T));
- result = (T)converter.ConvertFromString(value);
- return true;
- }
- Catch(Exception exception)
- {
-
-
- return false;
- }
- }
I have created this method with “Try-Parse” pattern so that it doesn’t break the application but simply returns ture/false if conversion is successful or failed due to exception or any other reasons. I found this classes in one the solution of Asp.net. You can find the complete class created for this blog post here.
Thumb Rule
Before you decide to jump into changing the business logic, try writing some tests for complete coverage of existing converter and then apply the changes and see if it’s not breaking any previously running cases. I wrote couple of tests to see if it works. You can find those tests for string to Converter here. These are not complete tests to validate every conversion, so use and test it by your own.