namespace MesETL.App; public class DataRecord : ICloneable { public static bool TryGetField(DataRecord record, string columnName, out string value) { value = string.Empty; if (record.Headers is null) throw new InvalidOperationException("Cannot get field when headers of a record have not been set."); var idx = IndexOfIgnoreCase(record.Headers, columnName); if (idx == -1) return false; value = record.Fields[idx]; return true; } public static string GetField(DataRecord record, string columnName) { if (record.Headers is null) throw new InvalidOperationException("Headers have not been set."); var idx = IndexOfIgnoreCase(record.Headers, columnName); if (idx is -1) throw new IndexOutOfRangeException( $"Column name '{columnName}' not found in this record, table name '{record.TableName}'."); return record.Fields[idx]; } private static int IndexOfIgnoreCase(IList list, string value) { var idx = -1; for (var i = 0; i < list.Count; i++) { if (list[i].Equals(value, StringComparison.OrdinalIgnoreCase)) { idx = i; break; } } return idx; } public IList Fields { get; } public IList Headers { get; } public string TableName { get; } public string? Database { get; set; } public long FieldCharCount { get; } public DataRecord(IEnumerable fields, string tableName, IEnumerable headers, string? database = null) { Fields = fields.ToList(); TableName = tableName; Headers = headers.ToList(); Database = database; if (Fields.Count != Headers.Count) throw new ArgumentException( $"The number of fields does not match the number of headers. Expected: {Headers.Count} Got: {Fields.Count} Fields: {string.Join(',', Fields)}", nameof(fields)); FieldCharCount = Fields.Sum(x => (long)x.Length); } public string this[int index] { get => Fields[index]; set => Fields[index] = value; } public string this[string columnName] { get => GetField(this, columnName); set => SetField(columnName, value); } public int FieldCount => Fields.Count; public bool TryGetField(string columnName, out string value) => TryGetField(this, columnName, out value); public bool SetField(string columnName, string value) => SetField(this, columnName, value); public bool SetField(DataRecord record, string columnName, string value) { if (record.Headers is null) throw new InvalidOperationException("Headers have not been set."); var idx = IndexOfIgnoreCase(record.Headers, columnName); if (idx is -1) throw new IndexOutOfRangeException( $"Column name '{columnName}' not found in this record, table name '{record.TableName}"); record.Fields[idx] = value; return true; } public void AddField(string columnName, string value) { if (IndexOfIgnoreCase(Headers, columnName) != -1) throw new InvalidOperationException($"{TableName}: 列名 '{columnName}' 已存在"); Fields.Add(value); Headers.Add(columnName); } public void RemoveField(string columnName) { var idx = IndexOfIgnoreCase(Headers, columnName); if (idx == -1) throw new InvalidOperationException($"{TableName}: 列名 '{columnName}' 不存在"); Fields.RemoveAt(idx); Headers.Remove(columnName); } public bool HeaderExists(string columnName) => IndexOfIgnoreCase(Headers, columnName) != -1; public object Clone() { return new DataRecord(new List(Fields), TableName, new List(Headers), Database); } }