namespace MesETL.App; public class DataRecord : ICloneable { 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; } private readonly List _fields; private readonly List _headers; /// /// 字段列表 /// public IReadOnlyList Fields => _fields; /// /// 表头列表 /// public IReadOnlyList Headers => _headers; /// /// 来源表名 /// public string TableName { get; } /// /// 需要输出的数据库 /// public string? Database { get; set; } /// /// 所有字段的总字符数量 /// public long FieldCharCount { get; } /// /// 忽略这个记录,不会被输出 /// public bool Ignore { get; set; } 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(columnName); set => SetField(columnName, value); } /// /// 尝试获取某个字段值 /// /// /// /// /// public bool TryGetField(string columnName, out string value) { value = string.Empty; if (_headers is null) throw new InvalidOperationException("Cannot get field when headers of a record have not been set."); var idx = IndexOfIgnoreCase(_headers, columnName); if (idx == -1) return false; value = _fields[idx]; return true; } /// /// 获取一条记录的某个字段值 /// TODO: 最好能优化至O(1) /// /// /// /// /// public string GetField(string columnName) { if (_headers is null) throw new InvalidOperationException("记录的表头尚未设置,无法赋值"); var idx = IndexOfIgnoreCase(_headers, columnName); if (idx is -1) throw new IndexOutOfRangeException( $"列 '{columnName}' 不存在于该纪录中,表名 '{TableName}"); return _fields[idx]; } /// /// 为记录的一个字段赋值,如果该字段名不存在则会抛出异常 /// /// 列名 /// 值 /// /// 该记录的表头尚未初始化,你可能在错误的阶段调用了该方法 /// 输入的字段名不存在于该记录中 public void SetField(string columnName, string value) { // 表头检查 if (_headers is null) throw new InvalidOperationException("记录的表头尚未设置,无法赋值"); var idx = IndexOfIgnoreCase(_headers, columnName); if (idx is -1) throw new IndexOutOfRangeException( $"列 '{columnName}' 不存在于该纪录中,表名 '{TableName}"); _fields[idx] = value; } /// /// 在记录中追加一个字段 /// /// 字段名 /// 字段值 /// 记录的表头尚未初始化,你可能在错误的阶段调用了此方法 /// 提供的字段名已存在于该记录中 public void AppendField(string columnName, string value) { if (_headers is null) throw new InvalidOperationException("记录的表头尚未设置,无法赋值"); var idx = IndexOfIgnoreCase(_headers, columnName); if (idx is > 0) throw new ArgumentException($"字段名 '{columnName}' 已存在于该记录中,无法重复添加", nameof(columnName)); _headers.Add(columnName); _fields.Add(value); } 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); } }