Azavea.Open.DAO.AbstractDaLayer.CoerceType C# (CSharp) Method

CoerceType() public method

Attempts to convert the value into the given type. While broadly similar to Convert.ChangeType, that method doesn't support enums and this one does. Calling that from within this method makes it take nearly twice as long, so this method does its own type checking.
public CoerceType ( Type desiredType, object input ) : object
desiredType System.Type Type we need the value to be.
input object Input value, may or may not already be the right type.
return object
        public virtual object CoerceType(Type desiredType, object input)
        {
            try
            {
                // For speed, put the most common checks at the top.
                if (desiredType.IsInstanceOfType(input))
                {
                    return input;
                }
                if (desiredType.Equals(typeof (string)))
                {
                    return Convert.ToString(input);
                }
                if (desiredType.Equals(typeof (int)))
                {
                    return input is string ? (int)Decimal.Parse((string)input) : Convert.ToInt32(input);
                }
                if (desiredType.Equals(typeof (long)))
                {
                    return input is string ? (long)Decimal.Parse((string)input) : Convert.ToInt32(input);
                }
                if (desiredType.Equals(typeof (double)))
                {
                    return Convert.ToDouble(input);
                }
                if (desiredType.Equals(typeof (DateTime)))
                {
                    return Convert.ToDateTime(input);
                }
                if (desiredType.IsEnum)
                {
                    return (input is int) ? input : Enum.Parse(desiredType, input.ToString());
                }
                if (desiredType.Equals(typeof (bool)))
                {
                    return Convert.ToBoolean(input);
                }
                if (desiredType.Equals(typeof (short)))
                {
                    return Convert.ToInt16(input);
                }
                if (desiredType.Equals(typeof (byte)))
                {
                    return Convert.ToByte(input);
                }
                if (desiredType.Equals(typeof (char)))
                {
                    return Convert.ToChar(input);
                }
                if (desiredType.Equals(typeof (float)))
                {
                    return (float) Convert.ToDouble(input);
                }
                if (desiredType.Equals(typeof (DateTime?)))
                {
                    if (input == null)
                    {
                        return null;
                    }
                    return Convert.ToDateTime(input);
                }
                if (desiredType.Equals(typeof(int?)))
                {
                    if (input == null)
                    {
                        return null;
                    }
                    return Convert.ToInt32(input);
                }
                if (desiredType.Equals(typeof(long?)))
                {
                    if (input == null)
                    {
                        return null;
                    }
                    return Convert.ToInt64(input);
                }
                if (desiredType.Equals(typeof(double?)))
                {
                    if (input == null)
                    {
                        return null;
                    }
                    return Convert.ToDouble(input);
                }
                if (desiredType.Equals(typeof (float?)))
                {
                    if (input == null)
                    {
                        return null;
                    }
                    return (float) Convert.ToDouble(input);
                }
                if (desiredType.Equals(typeof (bool?)))
                {
                    if (input == null)
                    {
                        return null;
                    }
                    return Convert.ToBoolean(input);
                }
                if (desiredType.Equals(typeof (byte[])))
                {
                    // Cast to byte array here so we'll throw if the type is incompatible.
                    // Technically we don't have to, since this returns object, but we want
                    // this to be the method that throws the type cast exception.
                    byte[] retVal = (byte[]) input;
                    return retVal;
                }
                // Nullables are generics, so nullable enums are more work to check for.
                if (desiredType.IsGenericType &&
                    desiredType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
                {
                    // Technically this first check will work for any nullable type, not just enums.
                    if (input == null)
                    {
                        return null;
                    }
                    // Note that we're only handling nullables, which have 1 generic param
                    // which is why the [0] is correct.
                    Type genericType = desiredType.GetGenericArguments()[0];
                    if (genericType.IsEnum)
                    {
                        return (input is int)
                            // Unlike normal enums, integers cannot simply be set on a nullable enum.
                            // So we have to call ToObject to convert it to an enum value first.
                            ? Enum.ToObject(genericType, input)
                            // Since it is a nullable enum, we're allowing blank or all-whitespace
                            // strings to count as nulls.
                            : (StringHelper.IsNonBlank(input.ToString())
                                ? Enum.Parse(genericType, input.ToString())
                                : null);
                    }
                }

                // For misc object types, we'll just check if it is already the correct type.
                if (desiredType.IsInstanceOfType(input))
                {
                    return input;
                }

                // If it's mapped as an AsciiString, put the value in as a byte array of
                // ascii characters.  This supports old-style (non-unicode) varchars.
                if (desiredType.Equals(typeof (AsciiString)))
                {
                    return Encoding.ASCII.GetBytes(input.ToString());
                }

                // Have subclasses be able to add their own coerced types.
                lock (this)
                {
                    if (_coerceableTypes != null)
                    {
                        foreach (Type t in _coerceableTypes.Keys)
                        {
                            if (t.IsAssignableFrom(desiredType))
                            {
                                return _coerceableTypes[t].DynamicInvoke(input);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new DaoTypeCoercionException(desiredType, input, e);
            }
            // To add support for lists, you'd need to add:
            //if (desiredType.IsSubclassOf(typeof(IList)))
            //{
            //    // input is some sort of list ID, so go run a subquery or something...
            //}
            // You'd also need to check if the input was a list, and do something special rather
            // than just try to convert it to an int or whatever.
            // Custom class types would be similar... Hmm, and you'd have to add support to the
            // class mapping to handle nested classes.  OK it's a tad more complicated, but it
            // is doable if necessary.
            // Oh yeah and then you have to handle transactions correctly, so if a second query fails
            // you remember to roll back the first one... And there are probably a billion other details...
            throw new DaoUnsupportedTypeCoercionException(desiredType, input);
        }