public static DetectTypeItem DetectType(string[] values) { var item = new DetectTypeItem(); DetectType(ref item, values); return(item); }
public static DetectTypeItem DetectType(string[] values) { if (values == null) { throw new ArgumentNullException(nameof(values)); } var log = new List <string>(); var type = typeof(string); var sizeMin = int.MaxValue; var sizeMax = 0; var decimalPrecision = 0; var decimalScale = 0; var isAscii = true; var haveEmpty = false; // Order matters. Strictest on the top. First available type will be returned. // If all values can be parsed to Int16 then it can be parsed to Int32 and Int64 too. var tcs = new TypeCode[] { TypeCode.Boolean, TypeCode.Byte, TypeCode.SByte, TypeCode.Int16, TypeCode.Int32, TypeCode.Int64, TypeCode.UInt16, TypeCode.UInt32, TypeCode.UInt64, TypeCode.Single, TypeCode.Char, TypeCode.DateTime, TypeCode.Double, TypeCode.Decimal, TypeCode.String, // TypeCode.DBNull, // TypeCode.Empty, // TypeCode.Object, }.ToList(); // All available types. var available = new Dictionary <TypeCode, Type>(); tcs.ForEach(x => available.Add(x, Type.GetType(nameof(System) + "." + x))); //Convert.ChangeType(value, colType); for (int i = 0; i < values.Length; i++) { var value = values[i]; if (string.IsNullOrEmpty(value)) { haveEmpty = true; continue; } // Determine string limits. sizeMin = Math.Min(sizeMin, value.Length); sizeMax = Math.Max(sizeMax, value.Length); isAscii &= value.All(x => x < 128); // Get available types to test against. var availableTypeCodes = available.Keys.ToArray(); // If only string was left. if (availableTypeCodes.Length == 1 && availableTypeCodes[0] == TypeCode.String) { break; } // Test against available types. foreach (var tc in availableTypeCodes) { switch (tc) { case TypeCode.Boolean: bool resultBool; if (!bool.TryParse(value, out resultBool)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.Byte: byte resultByte; if (!byte.TryParse(value, out resultByte)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.Char: char resultChar; if (!char.TryParse(value, out resultChar)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.DateTime: DateTime resultDateTime; if (!DateTime.TryParse(value, out resultDateTime)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.Decimal: decimal resultDecimal; if (!decimal.TryParse(value, out resultDecimal)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } var d = (System.Data.SqlTypes.SqlDecimal)resultDecimal; decimalPrecision = Math.Max(decimalPrecision, d.Precision); decimalScale = Math.Max(decimalScale, d.Scale); break; case TypeCode.Double: double resultDouble; if (!double.TryParse(value, out resultDouble)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.Int16: short resultShort; if (!short.TryParse(value, out resultShort)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.Int32: int resultInt; if (!int.TryParse(value, out resultInt)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.Int64: long resultLong; if (!long.TryParse(value, out resultLong)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.SByte: sbyte resultSByte; if (!sbyte.TryParse(value, out resultSByte)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.Single: float resultFloat; if (!float.TryParse(value, out resultFloat)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.UInt16: ushort resultUShort; if (!ushort.TryParse(value, out resultUShort)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.UInt32: uint resultUInt; if (!uint.TryParse(value, out resultUInt)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; case TypeCode.UInt64: ulong resultULong; if (!ulong.TryParse(value, out resultULong)) { log.Add(string.Format($"Removed {tc,-8} at {i,4} line. Value: {value}")); available.Remove(tc); } break; default: break; } } } type = available.FirstOrDefault().Value; var item = new DetectTypeItem() { Type = type, MinLength = sizeMin, MaxLength = sizeMax, IsAscii = isAscii, DecimalPrecision = decimalPrecision, DecimalScale = decimalScale, IsRequired = !haveEmpty, Log = log, }; return(item); }
public static void DetectType(ref DetectTypeItem item, params string[] values) { if (values == null) { throw new ArgumentNullException(nameof(values)); } if (item == null) { item = new DetectTypeItem(); } // Order matters. Strictest on the top. First available type will be returned. // If all values can be parsed to Int16 then it can be parsed to Int32 and Int64 too. //Convert.ChangeType(value, colType); for (int i = 0; i < values.Length; i++) { var value = values[i]; if (string.IsNullOrEmpty(value)) { item.IsRequired = false; continue; } // If minimum length not set then use available, otherwise get smaller. item.MinLength = item.MinLength == 0 ? value.Length : Math.Min(item.MinLength, value.Length); // Determine maximum length. item.MaxLength = Math.Max(item.MaxLength, value.Length); // Value is not ASCII if character code is outside of 128. item.IsAscii &= value.All(x => x < 128); // Test against available types. var tcs = item.AvailableTypes.ToArray(); foreach (var tc in tcs) { var remove = false; switch (tc) { case TypeCode.Boolean: bool resultBool; if (!bool.TryParse(value, out resultBool)) { remove = true; } break; case TypeCode.Byte: byte resultByte; if (!byte.TryParse(value, out resultByte)) { remove = true; } break; case TypeCode.Char: char resultChar; if (!char.TryParse(value, out resultChar)) { remove = true; } break; case TypeCode.DateTime: DateTime resultDateTime; if (!DateTime.TryParse(value, out resultDateTime)) { remove = true; } break; case TypeCode.Decimal: decimal resultDecimal; if (!decimal.TryParse(value, out resultDecimal)) { remove = true; } var d = (System.Data.SqlTypes.SqlDecimal)resultDecimal; item.DecimalPrecision = Math.Max(item.DecimalPrecision, d.Precision); item.DecimalScale = Math.Max(item.DecimalScale, d.Scale); break; case TypeCode.Double: double resultDouble; if (!double.TryParse(value, out resultDouble)) { remove = true; } break; case TypeCode.Int16: short resultShort; if (!short.TryParse(value, out resultShort) && !HaveLeadingZero(value)) { remove = true; } break; case TypeCode.Int32: int resultInt; if (!int.TryParse(value, out resultInt) && !HaveLeadingZero(value)) { remove = true; } break; case TypeCode.Int64: long resultLong; if (!long.TryParse(value, out resultLong) && !HaveLeadingZero(value)) { remove = true; } break; case TypeCode.SByte: sbyte resultSByte; if (!sbyte.TryParse(value, out resultSByte) && !HaveLeadingZero(value)) { remove = true; } break; case TypeCode.Single: float resultFloat; if (!float.TryParse(value, out resultFloat) && !HaveLeadingZero(value)) { remove = true; } break; case TypeCode.UInt16: ushort resultUShort; if (!ushort.TryParse(value, out resultUShort) && !HaveLeadingZero(value)) { remove = true; } break; case TypeCode.UInt32: uint resultUInt; if (!uint.TryParse(value, out resultUInt) && !HaveLeadingZero(value)) { remove = true; } break; case TypeCode.UInt64: ulong resultULong; if (!ulong.TryParse(value, out resultULong) && !HaveLeadingZero(value)) { remove = true; } break; default: break; } if (remove) { item.Log.Add(string.Format($"Removed {tc,-8} - Value: {value}")); item.AvailableTypes.Remove(tc); item.Type = item.AvailableTypes.Count == 0 ? null : Type.GetType("System." + item.AvailableTypes[0]); } } } }