public static class MimicCsvReader { public static IEnumerable Read( string filePath, Func, T?> parser, Func, bool>? filter = null) { using var reader = new StreamReader(filePath); var headerLine = reader.ReadLine(); if (headerLine is null) yield break; var headers = BuildHeaderIndex(headerLine); while (reader.ReadLine() is { } line) { if (string.IsNullOrWhiteSpace(line)) continue; var fields = line.Split(','); if (filter is not null && !filter(fields, headers)) continue; var record = parser(fields, headers); if (record is not null) yield return record; } } public static List ReadAll( string filePath, Func, T?> parser) { return Read(filePath, parser).ToList(); } private static Dictionary BuildHeaderIndex(string headerLine) { var headers = new Dictionary(StringComparer.OrdinalIgnoreCase); var columns = headerLine.Split(','); for (var i = 0; i < columns.Length; i++) headers[columns[i].Trim()] = i; return headers; } public static string Col(string[] fields, Dictionary headers, string name) { return headers.TryGetValue(name, out var idx) && idx < fields.Length ? fields[idx].Trim() : string.Empty; } public static int? ColInt(string[] fields, Dictionary headers, string name) { var val = Col(fields, headers, name); return int.TryParse(val, out var result) ? result : null; } public static decimal? ColDecimal(string[] fields, Dictionary headers, string name) { var val = Col(fields, headers, name); return decimal.TryParse(val, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var result) ? result : null; } public static DateTime? ColDateTime(string[] fields, Dictionary headers, string name) { var val = Col(fields, headers, name); return DateTime.TryParse(val, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var result) ? result : null; } }