A Flexible And Convenient Type Conversion Helper in C#

Every once in a while I need to convert objects of an unknown type into a known type; sometimes these types are only known at run time. In most cases I want the code to stay easy to read, so I don’t want to if-then-else the readybility of my code away.
Over the time, I have created a helper that performs the conversion in a convenient and fast way. Use it if you like.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;

namespace MunirHusseini
{
    public static class Conversion
    {
        /// <summary>
        /// Gets the specified property value and converts it, if necessary.
        /// </summary>
        /// <typeparam name="T">The type to convert to.</typeparam>
        /// <param name="o">The object to convert.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns></returns>
        public static T Convert<T>(this object o, T defaultValue = default(T))
        {
            if (o == null) return defaultValue;
            o = o.Convert(typeof(T), defaultValue);
            return o is T ? (T)o : defaultValue;
        }

        /// <summary>
        /// Gets the specified property value and converts it, if necessary.
        /// </summary>
        /// <param name="o">The object to convert.</param>
        /// <param name="type">The type to convert to.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns></returns>
        public static object Convert(this object o, Type type, object defaultValue)
        {
            if (o == null || o is DBNull) return defaultValue;
            if (type.IsInstanceOfType(o)) return o;

            try
            {
                object result;
                var s = o as string;

                if (s != null)
                {
                    if (s.Length == 0) return defaultValue;
                    result = Parse(type, s);
                    if (result != null) return result;
                }

                var valueType = o.GetType();
                var tc = TypeDescriptor.GetConverter(valueType);

                if (tc.CanConvertTo(type))
                {
                    result = tc.ConvertTo(o, type);
                    return result;
                }

                tc = TypeDescriptor.GetConverter(type);

                if (tc.CanConvertFrom(valueType))
                {
                    result = tc.ConvertFrom(o);
                    return result;
                }

                result = Parse(type, o) ?? defaultValue;
                return result;
            }
            catch
            {
                return Parse(type, o.ToString()) ?? defaultValue;
            }
        }

        /// <summary>
        /// Parses the specified object into the specified type.
        /// </summary>
        /// <param name="type">The type to parse into.</param>
        /// <param name="o">The object to parse.</param>
        /// <returns>An object of the specified type, if successfull; otherwise, null.</returns>
        public static object Parse(Type type, object o)
        {
            if (o == null) return null;
            var text = o.ToString();
            if (string.IsNullOrEmpty(text)) return null;

            object result = null;

            switch (type.Name)
            {
                case "UInt16":
                    {
                        UInt16 v2;
                        if (UInt16.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "UInt32":
                    {
                        UInt32 v2;
                        if (UInt32.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "UInt64":
                    {
                        UInt64 v2;
                        if (UInt64.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "Int16":
                    {
                        Int16 v2;
                        if (Int16.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "Int32":
                    {
                        Int32 v2;
                        if (Int32.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "Int64":
                    {
                        Int64 v2;
                        if (Int64.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "Byte":
                    {
                        Byte v2;
                        if (Byte.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "Boolean":
                    {
                        result = BooleanValues.Contains(text);
                        break;
                    }
                case "Decimal":
                    {
                        decimal v2;
                        if (decimal.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
                case "DateTime":
                    {
                        DateTime v2;
                        if (DateTime.TryParse(text, CultureInfo.InvariantCulture,
                                              DateTimeStyles.AllowInnerWhite | DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.AllowWhiteSpaces,
                                              out v2)) result = v2;
                        break;
                    }
                case "DateTimeOffset":
                    {
                        DateTimeOffset v2;
                        if (DateTimeOffset.TryParse(text, CultureInfo.InvariantCulture,
                                                    DateTimeStyles.AllowInnerWhite | DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.AllowWhiteSpaces,
                                                    out v2)) result = v2;
                        break;
                    }
                case "TimeSpan":
                    {
                        TimeSpan v2;
                        if (TimeSpan.TryParse(text, CultureInfo.InvariantCulture, out v2)) result = v2;
                        break;
                    }
            }

            return result;
        }

        private static readonly HashSet<string> BooleanValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "true", "1", "on", "yes", "ja" };
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s