Ejemplo n.º 1
0
 /// <summary>
 /// Test whether the input value is null or DBNull. Empty or whitespace strings
 /// will be treated as null according to options on <paramref name="options"/>
 /// </summary>
 public static bool IsNull(object value, ConvertOptions options)
 {
     if (null == value)
     {
         return(true);
     }
     if (value is DBNull)
     {
         return(true);
     }
     if (options.StringToNull && (value is string stringValue))
     {
         if (string.IsNullOrEmpty(stringValue))
         {
             return(true);
         }
         if (options.WhitespaceToNull && string.IsNullOrWhiteSpace(stringValue))
         {
             return(true);
         }
     }
     return(false);
 }
 /// <summary>
 /// Test if the input value is a non-null numeric type
 /// or a string that can be parsed as a number, with detection
 /// of hex strings controlled by ConvertOptions flags
 /// </summary>
 /// <param name="value"></param>
 /// <param name="options"></param>
 public static bool IsNumeric(object value, ConvertOptions options)
 {
     if (value == null)
     {
         return(false);
     }
     if (value is string sValue)
     {
         if (double.TryParse(sValue, out double d))
         {
             return(true);
         }
         if (options.HasFlag(ConvertOptions.AllowVBHex) && Regex.IsMatch(sValue, @"^\s*&[hH][0-9a-fA-F]+$"))
         {
             return(true);
         }
         if (options.HasFlag(ConvertOptions.Allow0xHex) && Regex.IsMatch(sValue, @"^\s*0[xX][0-9a-fA-F]+$"))
         {
             return(true);
         }
         return(false);
     }
     return(TypeInspection.IsNumberType(value.GetType()));
 }
Ejemplo n.º 3
0
 public Converter(ConvertOptions options) => throw null;
Ejemplo n.º 4
0
 /// <summary>
 /// Attempt to convert the input value to an equilavant representation in the target type.
 /// </summary>
 /// <param name="value">Any value</param>
 /// <param name="targetType">The Type to which the value should be converted</param>
 /// <param name="options">See <see cref="ConvertOptions"/></param>
 /// <remarks>If the target type is known at compile time, use the generic overload of Convert.To (<see cref="Convert.To{T}(object, ConvertOptions)"/>)</remarks>
 public static object To(object value, Type targetType, ConvertOptions options)
 {
     return(To(value, targetType, options, false, null));
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Attempt to convert the input value to an equilavant representation in the target type.
 /// </summary>
 /// <typeparam name="T">The Type to which the value should be converted</typeparam>
 /// <param name="value">Any value</param>
 /// <param name="options">See <see cref="Ockham.Data.ConvertOptions"/></param>
 /// <remarks>If the target type is not known at compile time, use the non-generic overload of Convert.To (<see cref="Convert.To(object, Type, ConvertOptions)"/>)</remarks>
 public static T To <T>(object value, ConvertOptions options)
 {
     return((T)(To(value, typeof(T), options, false, null)));
 }
        internal static object To(object value, Type targetType, ConvertOptions options, bool ignoreError, object defaultValue)
        {
            var typeInfo = targetType.GetTypeInfo();

            // Quick check #1: If input is null reference and target type is a reference type we can always safely return nothing
            if ((value == null) && (!typeInfo.IsValueType))
            {
                return(null);
            }

            // Quick check #2: If the input already is of the target type the return it immediately
            if (targetType.IsInstanceOfType(value))
            {
                return(value);
            }

            if (typeInfo.IsValueType)
            {
                // ---------------------------------------------------------------------------
                //  Special treatment of Nullable<T>. Although both C# and VB allow assignment
                //  and comparison of null literal to Nullable<T> values, the underlying type
                //  is actually a non-nullable struct (value type), thus we handle nullable
                //  types inside the section that handles value types
                // ---------------------------------------------------------------------------
                if (TypeInspection.IsNullableOfT(targetType))
                {
                    if (ValueInspection.IsNull(value, options))
                    {
                        // Nullable<T> of T is technically a struct, so IsValueType is true. However,
                        // semantics and implementation allow it to be treated as a reference type,
                        // so return null if the input is empty
                        return(null);
                    }
                    else
                    {
                        // Input is not an empty value, so convert to the underying type
                        try
                        {
                            // Note: DON'T ignore error on underlying conversion type
                            return(To(value, Nullable.GetUnderlyingType(targetType), options, false, null));
                        }
                        catch
                        {
                            if (ignoreError)
                            {
                                return(defaultValue ?? null);
                            }
                            throw;
                        }
                    }
                } // end IsNullable<T>

                // If input is empty, we can immediately return default or throw an exception
                if (ValueInspection.IsNull(value, options))
                {
                    if (options.HasFlag(ConvertOptions.NullToValueDefault))
                    {
                        //This is how we return the default value of a value type:
                        return(defaultValue ?? Activator.CreateInstance(targetType));
                    }
                    else
                    {
                        if (ignoreError)
                        {
                            return(defaultValue ?? Activator.CreateInstance(targetType));
                        }
                        throw new ArgumentNullException("value", "Cannot convert empty input value to value type " + targetType.FullName);
                    }
                }

                // We only got this far if the target type is a value type and the input value is not empty
                try
                {
                    // ---------------------------------------------------------------------------
                    //  Special treatment of Enums
                    // ---------------------------------------------------------------------------
                    if (typeInfo.IsEnum)
                    {
                        // Test IsNumeric BEFORE testing string so that numeric strings are
                        // treated as numbers, not as enum member names
                        if (ValueInspection.IsNumeric(value, options))
                        {
                            // If the input is a number or *numeric string*, first convert the
                            // input to an enum number value, then cast it using Enum.ToObject

                            // Note: DON'T ignore error on underlying conversion type
                            var rawValue = To(value, Enum.GetUnderlyingType(targetType), options, false, null);
                            return(Enum.ToObject(targetType, rawValue));
                        }
                        else if (value is string)
                        {
                            // Input is a string but Information.IsNumeric did not recognize it
                            // as a number. So, treat the input as an enum member name
                            string sEnumName = Regex.Replace((string)value, @"[\s\r\n]+", "");
                            return(Enum.Parse(targetType, sEnumName, true));
                        }
                        else
                        {
                            // Fallback: Attempt to convert the input to the underlying numeric type, even if
                            // Information.IsNumeric returned false

                            // Note: DON'T ignore error on underlying conversion type
                            var rawValue = To(value, Enum.GetUnderlyingType(targetType), options, false, null);
                            return(Enum.ToObject(targetType, rawValue));
                        }
                    } // end IsEnum

                    // ---------------------------------------------------------------------------
                    //  Use hand-written conversion functions for specific types
                    // ---------------------------------------------------------------------------
                    if (targetType == typeof(Guid))
                    {
                        // Use special conversion logic for converting to a Guid
                        return(_ToGuid(value));
                    }
                    else if (targetType == typeof(TimeSpan))
                    {
                        // Use special conversion logic for converting to a TimeSpan
                        return(_ToTimeSpan(value));
                    }
                    else if (targetType == typeof(bool))
                    {
                        // Use special conversion logic for converting to Boolean
                        return(_ToBool(value));
                    }

                    // ---------------------------------------------------------------------------
                    //  Invoke IConvertible implementation, if any
                    // ---------------------------------------------------------------------------
                    if (value is IConvertible iConvertible)
                    {
                        // Use the System.ChangeType method, which makes full use of any IConvertible implementation on the target type
                        try
                        {
                            return(System.Convert.ChangeType(value, targetType));
                        }
                        catch
                        {
                            // Ignore exception and fall back to VBConvert implementation
                        }
                    }

                    // ---------------------------------------------------------------------------
                    //  Fall back to VBConvert methods
                    // ---------------------------------------------------------------------------
                    switch (System.Convert.GetTypeCode(targetType))
                    {
                    case TypeCode.Boolean:
                        // Use custom ToBool method
                        return(_ToBool(value));

                    case TypeCode.Byte:
                        return(VBConvert.ToByte(value));

                    case TypeCode.Char:
                        return(VBConvert.ToChar(value));

                    case TypeCode.DateTime:
                        return(VBConvert.ToDate(value));

                    case TypeCode.Decimal:
                        return(VBConvert.ToDecimal(value));

                    case TypeCode.Double:
                        return(VBConvert.ToDouble(value));

                    case TypeCode.Int16:
                        return(VBConvert.ToShort(value));

                    case TypeCode.Int32:
                        return(VBConvert.ToInteger(value));

                    case TypeCode.Int64:
                        return(VBConvert.ToLong(value));

                    case TypeCode.SByte:
                        return(VBConvert.ToSByte(value));

                    case TypeCode.Single:
                        return(VBConvert.ToSingle(value));

                    case TypeCode.String:
                        return(VBConvert.ToString(value));

                    case TypeCode.UInt16:
                        return(VBConvert.ToUShort(value));

                    case TypeCode.UInt32:
                        return(VBConvert.ToUInteger(value));

                    case TypeCode.UInt64:
                        return(VBConvert.ToULong(value));
                    }

                    // ---------------------------------------------------------------------------
                    //  Fall back to VBConvert.ChangeType
                    // ---------------------------------------------------------------------------
                    return(VBConvert.ChangeType(value, targetType));
                }
                catch (Exception ex)
                {
                    // Conversion of non-empty value to value type failed.
                    if (ignoreError)
                    {
                        return(defaultValue ?? Activator.CreateInstance(targetType));
                    }
                    throw new InvalidCastException($"Cannot convert {_FormatValue(value)} to type {targetType.FullName}", ex);
                }
            } // end IsValueType
            else
            {
                // Reference types...not much to do here besides check for empty values

                if (ValueInspection.IsNull(value, options))
                {
                    return(null);
                }

                try
                {
                    //  Fall back to VBConvert.ChangeType
                    return(VBConvert.ChangeType(value, targetType));
                }
                catch
                {
                    if (ignoreError)
                    {
                        return(defaultValue ?? null);
                    }
                    throw;
                }
            }
        }
Ejemplo n.º 7
0
 // Initialize from existing ConvertOptions
 public static ConvertOptionsBuilder FromConvertOptions(ConvertOptions source) => throw null;
Ejemplo n.º 8
0
 public static object To(object value, Type targetType, ConvertOptions options) => throw null;
Ejemplo n.º 9
0
 /// <summary>
 /// Test if the input value is a non-null numeric type
 /// or a string that can be parsed as a number, with detection
 /// of hex strings controlled by ConvertOptions flags
 /// </summary>
 /// <param name="value"></param>
 /// <param name="options"></param>
 public static bool IsNumeric(object value, ConvertOptions options) => IsNumeric(value, options.Numbers.ParseFlags);
Ejemplo n.º 10
0
 public static Guid ToGuid(object value, ConvertOptions options) => throw null;
Ejemplo n.º 11
0
 public static object ToDBNull(object value, ConvertOptions options) => throw null;
 /// <summary>
 /// Test whether the input value is null or DBNull. Will also return true if <paramref name="options"/>
 /// includes the <see cref="ConvertOptions.EmptyStringAsNull"/> flag and <paramref name="value"/> is an empty string.
 /// </summary>
 public static bool IsNull(object value, ConvertOptions options)
 {
     return(IsNull(value, options.HasFlag(ConvertOptions.EmptyStringAsNull)));
 }
 public static TimeSpan ToTimeSpan(object value, ConvertOptions options) => throw null;
Ejemplo n.º 14
0
        private static FlattenedOptions FlattenOptions(ConvertOptions options)
        {
            var flatOptions = FlattenedOptions.None;

            // Enums
            if (options.Enums.IgnoreUndefinedNames)
            {
                flatOptions |= FlattenedOptions.IgnoreEnumNames;
            }
            if (options.Enums.IgnoreUndefinedValues)
            {
                flatOptions |= FlattenedOptions.IgnoreEnumValues;
            }
            if (options.Enums.CoerceUndefinedValues)
            {
                flatOptions |= FlattenedOptions.CoerceEnumValues;
            }

            // Numbers
            if (options.Numbers.ParseHex)
            {
                flatOptions |= FlattenedOptions.ParseHex;
            }
            if (options.Numbers.ParseOctal)
            {
                flatOptions |= FlattenedOptions.ParseOctal;
            }
            if (options.Numbers.ParseBinary)
            {
                flatOptions |= FlattenedOptions.ParseBinary;
            }
            if (options.Numbers.AllowDigitSeparator)
            {
                flatOptions |= FlattenedOptions.AllowDigitSeparator;
            }

            // Strings
            if (options.Strings.TrimStart)
            {
                flatOptions |= FlattenedOptions.TrimStart;
            }
            if (options.Strings.TrimEnd)
            {
                flatOptions |= FlattenedOptions.TrimEnd;
            }
            if (options.Strings.EmptyStringAsNull)
            {
                flatOptions |= FlattenedOptions.EmptyStringAsNull;
            }
            if (options.Strings.WhitespaceAsNull)
            {
                flatOptions |= FlattenedOptions.WhitespaceAsNull;
            }

            // Value types
            if (options.ValueTypes.NullToValueDefault)
            {
                flatOptions |= FlattenedOptions.NullToValueDefault;
            }

            return(flatOptions);
        }
Ejemplo n.º 15
0
 public Converter(ConvertOptions options)
 {
     Options = options;
 }
        } = new ConvertOptionsBuilder();                                                   // Note ConvertOptionsBuilder is immutable, so we can always return the same instance here

        /// <summary>
        /// Intialize a <see cref="ConvertOptionsBuilder"/> with the options from an existing <see cref="ConvertOptions"/> instance
        /// </summary>
        public static ConvertOptionsBuilder FromConvertOptions(ConvertOptions source) => new ConvertOptionsBuilder(source.AllOptions(), source.Converters);
Ejemplo n.º 17
0
 public static T To <T>(object value, ConvertOptions options) => throw null;