You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于当前月份更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:55:08