Esempio n. 1
0
        /// <summary>
        ///     Performs custom conversion for enumeration values to allow flagged enumerators to be converted from, using compound numeric values or delimited strings
        /// </summary>
        /// <typeparam name="T">
        ///     The data type which the specified value should be converted to, if possible.
        /// </typeparam>
        /// <param name="value">
        ///     The value to be converted
        /// </param>
        /// <param name="result">
        ///     The converted equivelent of the specified <i>value</i>, or the default value for the specified type, <i>T</i>, where conversion has failed.
        /// </param>
        /// <returns>
        ///     A <see cref="T:System.Boolean" /> value which indicates if conversion succeeded
        /// </returns>
        private static Boolean AttemptEnumeratorConversion <T>(Object value, out T result)
        {
            Boolean success;

            // Get the type or, for nullable types, the underlying type
            Type underlyingType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);

            if (value == null || value == DBNull.Value)
            {
                // Conversion failed, no value provided
                result  = default(T);
                success = false;
            }
            else if (!underlyingType.IsEnum)
            {
                // Conversion failed, type is not an enumerator
                result  = default(T);
                success = false;
            }
            else if (value is Guid)
            {
                result  = default(T);
                success = false;

                // Loop through each defined enumeration and compare the enumeration guid with the guid specified.
                foreach (T enumeration in Enum.GetValues(underlyingType))
                {
                    EnumerationGuid guid = underlyingType.GetField(enumeration.ToString(), BindingFlags.Public | BindingFlags.Static).GetCustomAttributes <EnumerationGuid>().FirstOrDefault();
                    if (guid != null && Guid.Equals(guid.Guid, value))
                    {
                        result  = enumeration;
                        success = true;
                        break;
                    }
                }
            }
            else if (value is String)
            {
                success = true;
                Int64 checkedValue = 0;

                // Remove leading and trailing spaces from each element and separate by multiple known delimiters (commas, pipes, etc)
                IEnumerable <String> stringValueCollection = value.ToString().Split(Conversion.ENUMERATOR_DELIMITERS, StringSplitOptions.RemoveEmptyEntries).Select(val => val.Trim());
                foreach (String stringValue in stringValueCollection)
                {
                    // Get the enumeration which matches the string value (case-insensitive)
                    IEnumerable <T> enumeration = Enum.GetValues(underlyingType).OfType <T>().Where(enumValue => String.Equals(stringValue, Enum.GetName(underlyingType, enumValue), StringComparison.OrdinalIgnoreCase));
                    if (enumeration.Count() == 0)
                    {
                        success = false;
                    }
                    else
                    {
                        checkedValue |= Convert.ToInt64(enumeration.First());
                    }
                }

                // Convert the compounded result to the enumerators underlying type, if all enumeration values were converted successfully
                if (success)
                {
                    result = (T)Convert.ChangeType(checkedValue, Enum.GetUnderlyingType(underlyingType));
                }
                else
                {
                    result = default(T);
                }
            }
            else if (value is Byte || value is SByte || value is Int16 || value is UInt16 || value is Int32 || value is UInt32 || value is Int64 || value is UInt64)
            {
                Int64 checkedValue = 0;
                Int64 numeralValue = Convert.ToInt64(value);

                // Test the specified numeric value against each enumeration value and compound the value to the result
                foreach (Object enumeration in Enum.GetValues(underlyingType))
                {
                    Int64 enumValue = Convert.ToInt64(enumeration);
                    if ((numeralValue & enumValue) == enumValue)
                    {
                        checkedValue |= enumValue;
                    }
                }

                // Convert the compounded result to the enumerators underlying type
                result  = (T)Enum.ToObject(underlyingType, Convert.ChangeType(checkedValue, Enum.GetUnderlyingType(underlyingType)));
                success = true;
            }
            else
            {
                // Conversion failure: value is neither a string nor a numeric type
                result  = default(T);
                success = false;
            }

            return(success);
        }
Esempio n. 2
0
        /// <summary>
        ///    Converts the specified <paramref name="value" /> to the specified data type, falling back to a default value where conversion cannot be achieved
        /// </summary>
        /// <typeparam name="T">
        ///     The data type which the specified value should be converted to, if possible.
        /// </typeparam>
        /// <param name="value">
        ///     The value to be converted
        /// </param>
        /// <param name="defaultValue">
        ///     The default value to be returned if conversion cannot be achieved
        /// </param>
        /// <returns>
        ///     Returns the converted value or, where conversion fails, the specified default value
        /// </returns>
        private static T AttemptConversion <T>(Object value, T defaultValue)
        {
            // Defines the value to be returned.  This local variable is uninitialised to ensure that all scenarios have been catered for within this method,
            // as a compiler warning will be generated (for using an uninitialised local variable) if any scenarios is missed.
            T returnValue;
            T parsedValue;

            // Identify the absolute type (for System.Nullable wrapped types)
            Type    absoluteType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
            Boolean isNumeric    = (value != null && value != DBNull.Value) && (value.GetType().IsEnum || value.GetType() == typeof(SByte) || value.GetType() == typeof(Int16) || value.GetType() == typeof(Int32) || value.GetType() == typeof(Int64) || value.GetType() == typeof(Decimal) || value.GetType() == typeof(Double) || value.GetType() == typeof(Single) || value.GetType() == typeof(Byte) || value.GetType() == typeof(UInt16) || value.GetType() == typeof(UInt32) || value.GetType() == typeof(UInt64));

            // Check if the value is null (or a null-equivelent)
            if (value == null || (Object)(value) == DBNull.Value)
            {
                // If the specified type is a value type, then null cannot be converted because value types (structs) are non-nullable
                if (typeof(T).IsValueType)
                {
                    // Conversion failed - value type does not allow null value
                    returnValue = defaultValue;
                }
                else
                {
                    returnValue = (T)(Object)null;
                }
            }

            // Perform boxing if specified value is already of the required type or can be assigned to the specified type
            else if (value != null && (value is T || typeof(T).IsAssignableFrom(value.GetType())))
            {
                returnValue = (T)value;
            }

            // If conversion can be achieved dynamically, using a custom-conversion method, perform the conversion and return the result of the conversion
            else if (Conversion.AttemptCustomConversion <T>(value, out parsedValue))
            {
                returnValue = parsedValue;
            }

            // If the specified type is an enumerator, invoke custom conversion logic to perform the conversion
            else if (Conversion.AttemptEnumeratorConversion <T>(value, out parsedValue))
            {
                returnValue = parsedValue;
            }

            // If conversion can be achieved dynamically, using a standard Microsoft.NET method, perform the conversion and return the result of the conversion
            else if (Conversion.AttemptStandardConversion <T>(value, out parsedValue))
            {
                returnValue = parsedValue;
            }

            else if (absoluteType == typeof(Guid) && value.GetType().IsEnum)
            {
                EnumerationGuid guid = value.GetType().GetField(value.ToString(), BindingFlags.Public | BindingFlags.Static).GetCustomAttributes().OfType <EnumerationGuid>().FirstOrDefault();
                if (guid != null)
                {
                    returnValue = (T)(Object)guid.Guid;
                }
                else
                {
                    returnValue = defaultValue;
                }
            }

            // If converting to a string, use the ToString method with a predefined formatting standard.  For enumerators, use the value of the description attribute
            else if (typeof(T) == typeof(String))
            {
                if (value is Enum)
                {
                    returnValue = (T)(Object)(value.GetType().GetField(value.ToString(), BindingFlags.Public | BindingFlags.Static).GetCustomAttributes(true).OfType <DescriptionAttribute>().Select(attr => attr.Description).FirstOrDefault() ?? value.ToString());
                }
                else if (value is Int16 || value is Int32 || value is Int64)
                {
                    returnValue = (T)(Object)Convert.ToInt64(value).ToString("0");
                }
                else if (value is UInt16 || value is UInt32 || value is UInt64)
                {
                    returnValue = (T)(Object)Convert.ToUInt64(value).ToString("0");
                }
                else if (value is Decimal)
                {
                    returnValue = (T)(Object)((Decimal)value).ToString("0.00");
                }
                else if (value is Double)
                {
                    returnValue = (T)(Object)((Double)value).ToString("0.00");
                }
                else if (value is Single)
                {
                    returnValue = (T)(Object)((Single)value).ToString("0.00");
                }
                else if (value is DateTime)
                {
                    returnValue = (T)(Object)((DateTime)value).ToString("dd MMMM yyyy");
                }
                else if (value is TimeSpan)
                {
                    returnValue = (T)(Object)((TimeSpan)value).ToString("HH:mm");
                }
                else if (value is Boolean)
                {
                    returnValue = (T)(Object)((Boolean)value ? "Yes" : "No");
                }
                else
                {
                    returnValue = (T)(Object)value.ToString();
                }
            }

            // Attempt conversion from one numeral type to another numeral type
            else if (isNumeric && absoluteType == typeof(SByte))
            {
                try { returnValue = (T)(Object)Convert.ToSByte(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(Int16))
            {
                try { returnValue = (T)(Object)Convert.ToInt16(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(Int32))
            {
                try { returnValue = (T)(Object)Convert.ToInt32(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(Int64))
            {
                try { returnValue = (T)(Object)Convert.ToInt64(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(Decimal))
            {
                try { returnValue = (T)(Object)Convert.ToDecimal(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(Double))
            {
                try { returnValue = (T)(Object)Convert.ToDouble(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(Single))
            {
                try { returnValue = (T)(Object)Convert.ToSingle(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(Byte))
            {
                try { returnValue = (T)(Object)Convert.ToByte(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(UInt16))
            {
                try { returnValue = (T)(Object)Convert.ToUInt16(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(UInt32))
            {
                try { returnValue = (T)(Object)Convert.ToUInt32(value); }
                catch { returnValue = defaultValue; }
            }
            else if (isNumeric && absoluteType == typeof(UInt64))
            {
                try { returnValue = (T)(Object)Convert.ToUInt64(value); }
                catch { returnValue = defaultValue; }
            }
            else if (absoluteType == typeof(Byte))
            {
                try {
                    returnValue = value.ToString() == "True" ? (T)(Object)Convert.ToByte(1) : (T)(Object)Convert.ToByte(0);
                }
                catch { returnValue = defaultValue; }
            }

            // If all conversion attempts have failed, fall back to the specified default value
            else
            {
                returnValue = defaultValue;
            }

            return(returnValue);
        }