public DataTable StronglyTypeTable(DataTable workingTable, ExplicitTypingCollection explicitTypingCollection) { Dictionary <int, IDecideTypesForStrings> deciders = new Dictionary <int, IDecideTypesForStrings>(); var factory = new TypeDeciderFactory(_culture); if (!string.IsNullOrWhiteSpace(_explicitDateTimeFormat)) { factory.Settings.ExplicitDateFormats = new [] { _explicitDateTimeFormat } } ; DataTable dtCloned = workingTable.Clone(); bool typeChangeNeeded = false; foreach (DataColumn col in workingTable.Columns) { //if we have already handled it if (explicitTypingCollection != null && explicitTypingCollection.ExplicitTypesCSharp.ContainsKey(col.ColumnName)) { continue; } //let's make a decision about the data type to use based on the contents var computedType = new Guesser(); computedType.AdjustToCompensateForValues(col); //Type based on the contents of the column if (computedType.ShouldDowngradeColumnTypeToMatchCurrentEstimate(col)) { dtCloned.Columns[col.ColumnName].DataType = computedType.Guess.CSharpType; //if we have a type decider to parse this data type if (factory.IsSupported(computedType.Guess.CSharpType)) { deciders.Add(col.Ordinal, factory.Create(computedType.Guess.CSharpType)); //record column index and parser } typeChangeNeeded = true; } } if (typeChangeNeeded) { foreach (DataRow row in workingTable.Rows) { dtCloned.Rows.Add(row.ItemArray.Select((v, idx) => deciders.ContainsKey(idx) && v is string s? deciders[idx].Parse(s) : v).ToArray()); } return(dtCloned); } return(workingTable); }