如何通过List<Dictionary<string,object>>更新类属性且不使用反射及AutoMapper
可行实现方案(无反射、无第三方依赖)
你当前是PoC项目且最多仅需要处理8个属性的更新,直接手写静态属性映射委托表是性能最优、代码量最小的方案,该方案和硬编码赋值性能一致,完全不需要反射或AutoMapper组件。
实现逻辑如下:
- 提前为
FlowPage类定义静态的属性名到赋值动作的映射关系,仅在程序启动时初始化一次,运行时无额外开销 - 遍历传入的字典键值对时直接匹配映射表执行赋值,同时可灵活添加类型合法性校验
完整代码示例
首先在你的业务类中定义静态属性映射表:
// 作为静态成员仅初始化一次,后续新增可更新属性仅需在此添加映射即可 private static readonly Dictionary<string, Action<FlowPage, object>> _pagePropertySetters = new() { ["Title"] = (page, value) => page.Title = Convert.ToString(value), ["SortOrder"] = (page, value) => page.SortOrder = Convert.ToInt32(value), ["IsPublished"] = (page, value) => page.IsPublished = Convert.ToBoolean(value), ["Content"] = (page, value) => page.Content = Convert.ToString(value), // 其他需要支持更新的属性依次补充即可,8个属性写起来成本极低 };
补全你的业务方法逻辑:
public async Task<Errors> UpdatePageForProject(Guid projectId, List<Dictionary<string, object>> data) { if (!IsValidUserIdForProject(projectId)) return new Errors { ErrorMessage = "Project does not exist", Success = false }; if (data.Count == 0) return new Errors { ErrorMessage = "No data passed to change", Success = false }; var page = await _context.FlowPages.FirstOrDefaultAsync(t => t.ProjectId == projectId); // 补充空对象校验,避免空引用异常 if (page == null) return new Errors { ErrorMessage = "Page not found for the project", Success = false }; foreach (var d in data) { foreach (var (key, value) in d) { // 匹配到预定义的属性规则就执行赋值 if (_pagePropertySetters.TryGetValue(key, out var setter)) { try { setter.Invoke(page, value); } catch (Exception ex) { // 可按需添加类型转换错误的自定义处理逻辑 return new Errors { ErrorMessage = $"Invalid value for property {key}: {ex.Message}", Success = false }; } } // 不匹配的Key可直接忽略,也可按需添加未知参数报错逻辑 } } // 提交更新到数据库 await _context.SaveChangesAsync(); return new Errors { Success = true }; }
方案优势
- 完全无反射、无第三方依赖,运行性能和硬编码赋值完全一致
- 维护成本极低,后续新增可更新属性仅需要在映射表中加一行配置
- 可灵活自定义每个属性的类型转换逻辑、校验规则,兼容性更强
内容的提问来源于stack exchange,提问作者Nodoid
相关产品推荐
相关产品推荐

