基于当前月份更新C#中List<TimeControlGrid>集合项的技术问询
实现思路与代码示例
刚好做过类似的需求,咱们一步步来搞定这个逻辑:
首先得明确核心规则:当前月份为N时,需要更新N到12月的所有对应字段(比如1月更全部12个,11月更11、12月,12月仅更12月)。
先假设你的实体类结构(根据实际调整)
首先咱们得明确TimeControlGrid的结构,我这里先按常规场景定义:
public class TimeControlGrid { public int EmpId { get; set; } // 员工唯一标识,用来匹配DataTable记录 public string EmpName { get; set; } public decimal Jan { get; set; } public decimal Feb { get; set; } public decimal Mar { get; set; } public decimal Apr { get; set; } public decimal May { get; set; } public decimal Jun { get; set; } public decimal Jul { get; set; } public decimal Aug { get; set; } public decimal Sep { get; set; } public decimal Oct { get; set; } public decimal Nov { get; set; } public decimal Dec { get; set; } }
方式一:直观的Switch写法(适合字段固定、不想用反射的场景)
这种写法逻辑直白,新手也能快速看懂:
// 1. 获取当前月份(1-12) int currentMonth = DateTime.Now.Month; // 2. 把DataTable转成字典,用员工ID当Key,快速匹配记录(避免嵌套遍历拖慢效率) var employeeDataDict = yourDataTable.AsEnumerable() .ToDictionary(row => row.Field<int>("EmpId"), row => row); // 3. 遍历List集合,逐个更新字段 foreach (var empItem in EmpList) { // 先找到DataTable中对应的员工记录 if (employeeDataDict.TryGetValue(empItem.EmpId, out var matchedRow)) { // 根据当前月份,更新对应范围的字段 switch (currentMonth) { case 1: // 1月更新所有月份 empItem.Jan = matchedRow.Field<decimal>("Jan"); empItem.Feb = matchedRow.Field<decimal>("Feb"); empItem.Mar = matchedRow.Field<decimal>("Mar"); empItem.Apr = matchedRow.Field<decimal>("Apr"); empItem.May = matchedRow.Field<decimal>("May"); empItem.Jun = matchedRow.Field<decimal>("Jun"); empItem.Jul = matchedRow.Field<decimal>("Jul"); empItem.Aug = matchedRow.Field<decimal>("Aug"); empItem.Sep = matchedRow.Field<decimal>("Sep"); empItem.Oct = matchedRow.Field<decimal>("Oct"); empItem.Nov = matchedRow.Field<decimal>("Nov"); empItem.Dec = matchedRow.Field<decimal>("Dec"); break; case 2: // 2月更新2-12月 empItem.Feb = matchedRow.Field<decimal>("Feb"); empItem.Mar = matchedRow.Field<decimal>("Mar"); empItem.Apr = matchedRow.Field<decimal>("Apr"); empItem.May = matchedRow.Field<decimal>("May"); empItem.Jun = matchedRow.Field<decimal>("Jun"); empItem.Jul = matchedRow.Field<decimal>("Jul"); empItem.Aug = matchedRow.Field<decimal>("Aug"); empItem.Sep = matchedRow.Field<decimal>("Sep"); empItem.Oct = matchedRow.Field<decimal>("Oct"); empItem.Nov = matchedRow.Field<decimal>("Nov"); empItem.Dec = matchedRow.Field<decimal>("Dec"); break; // ... 这里依次补充case 3到case 10的逻辑,和上面格式一致 case 11: // 11月更新11、12月 empItem.Nov = matchedRow.Field<decimal>("Nov"); empItem.Dec = matchedRow.Field<decimal>("Dec"); break; case 12: // 12月仅更新12月 empItem.Dec = matchedRow.Field<decimal>("Dec"); break; default: // 处理异常月份(理论上不会走到这里),比如打日志 Console.WriteLine($"无效的月份:{currentMonth}"); break; } } else { // 处理DataTable中找不到对应员工的情况,比如记录日志或者跳过 Console.WriteLine($"员工ID {empItem.EmpId} 在DataTable中无匹配记录"); } }
方式二:反射优化版(适合字段可能变动、不想写大量switch的场景)
如果后续月份字段可能调整,或者不想写12个case,用反射+映射表的方式更简洁易维护:
// 1. 定义月份数字和字段名的映射关系 var monthToFieldMap = new Dictionary<int, string> { {1, "Jan"}, {2, "Feb"}, {3, "Mar"}, {4, "Apr"}, {5, "May"}, {6, "Jun"}, {7, "Jul"}, {8, "Aug"}, {9, "Sep"}, {10, "Oct"}, {11, "Nov"}, {12, "Dec"} }; // 2. 获取当前月份 int currentMonth = DateTime.Now.Month; // 3. 构建DataTable的快速查找字典 var employeeDataDict = yourDataTable.AsEnumerable() .ToDictionary(row => row.Field<int>("EmpId"), row => row); // 4. 获取TimeControlGrid的属性信息(提前缓存,避免每次遍历都反射) var empProperties = typeof(TimeControlGrid).GetProperties(); // 5. 遍历List并更新字段 foreach (var empItem in EmpList) { if (employeeDataDict.TryGetValue(empItem.EmpId, out var matchedRow)) { // 遍历从当前月份到12月的所有月份 for (int month = currentMonth; month <= 12; month++) { string fieldName = monthToFieldMap[month]; // 从DataTable中取新值(注意类型要和实体类一致,这里用decimal举例) decimal newValue = matchedRow.Field<decimal>(fieldName); // 找到实体类对应的属性并赋值 var targetProperty = empProperties.First(p => p.Name.Equals(fieldName, StringComparison.OrdinalIgnoreCase)); targetProperty.SetValue(empItem, newValue); } } else { Console.WriteLine($"员工ID {empItem.EmpId} 在DataTable中无匹配记录"); } }
注意事项
- 字段名一致性:确保DataTable的月份字段名和
TimeControlGrid的属性名完全一致(如果大小写不敏感,可以在反射时加StringComparison.OrdinalIgnoreCase) - 唯一标识正确性:用来匹配的员工ID必须是唯一的,否则
ToDictionary会抛出重复键异常;如果有重复场景,可以改用ToLookup - 类型匹配:DataTable中的字段类型要和实体类属性类型一致(比如都是decimal或int),否则
Field<T>方法会报错 - 异常处理:实际项目中建议添加日志记录,比如反射找不到属性、DataTable字段为空的情况
内容的提问来源于stack exchange,提问作者sandeep
相关产品推荐
相关产品推荐

