如何优化BigObject模型的选择性数据填充逻辑?
优化方案:基于Builder模式的可配置填充实现
1. 拆分字段填充逻辑
先把DataService中每个字段的填充逻辑抽离成独立方法,明确依赖关系,避免后续Builder耦合过多业务细节:
class DataService { // 封装各字段的数据源调用逻辑 private TypeA GetDataA() => sourceServiceA.GetData(); private TypeB GetDataB(TypeA dataA) => sourceServiceB.GetData(dataA.Id); private TypeC GetDataC() => sourceServiceC.GetData(); // 默认全量填充入口 public BigObject GetFullModel() => new BigObjectBuilder().WithAll().Build(this); }
2. 实现BigObjectBuilder
Builder类负责管理填充规则、处理依赖(比如填充DataB必须先确保DataA已填充),同时支持灵活配置可选字段:
class BigObjectBuilder { private readonly HashSet<string> _targetFields = new HashSet<string>(); private bool _enforceRequired = true; // 默认校验必填字段,可关闭 // 用常量定义字段标识,避免硬编码字符串 private const string FieldDataA = nameof(BigObject.DataA); private const string FieldDataB = nameof(BigObject.DataB); private const string FieldDataC = nameof(BigObject.DataC); // 链式配置方法:仅填充DataA public BigObjectBuilder WithDataA() { _targetFields.Add(FieldDataA); return this; } // 填充DataB时自动加入依赖的DataA public BigObjectBuilder WithDataB() { _targetFields.Add(FieldDataA); _targetFields.Add(FieldDataB); return this; } public BigObjectBuilder WithDataC() { _targetFields.Add(FieldDataC); return this; } // 配置全量填充 public BigObjectBuilder WithAll() { _targetFields.Add(FieldDataA); _targetFields.Add(FieldDataB); _targetFields.Add(FieldDataC); return this; } // 排除指定字段(配合WithAll使用) public BigObjectBuilder WithoutDataC() { _targetFields.Remove(FieldDataC); return this; } // 核心构建方法,依赖DataService提供的填充逻辑 public BigObject Build(DataService dataService) { var model = new BigObject(); // 处理DataA:只要目标字段包含DataA或依赖它的DataB,就填充 if (_targetFields.Contains(FieldDataA) || _targetFields.Contains(FieldDataB)) { model.DataA = dataService.GetDataA(); } // 处理DataB:仅当明确要求填充,且DataA已存在 if (_targetFields.Contains(FieldDataB) && model.DataA != null) { model.DataB = dataService.GetDataB(model.DataA); } // 处理DataC if (_targetFields.Contains(FieldDataC)) { model.DataC = dataService.GetDataC(); } // 必填字段校验:比如DataA是必填项,未填充则抛出异常 if (_enforceRequired && model.DataA == null) { throw new InvalidOperationException("DataA为必填字段,必须填充"); } return model; } }
3. 调用方式示例
通过链式调用灵活配置填充规则,无需关心内部依赖:
var dataService = new DataService(); // 仅填充DataA var model1 = new BigObjectBuilder().WithDataA().Build(dataService); // 自动处理依赖:填充DataA+DataB var model2 = new BigObjectBuilder().WithDataB().Build(dataService); // 填充DataA+DataC var model3 = new BigObjectBuilder().WithDataA().WithDataC().Build(dataService); // 全量填充但排除DataC var model4 = new BigObjectBuilder().WithAll().WithoutDataC().Build(dataService);
4. 兼容原有配置类(可选)
如果需要保留类似BigObjectFilter的配置方式,可以给Builder添加从配置初始化的方法:
class BigObjectFillConfig { public bool FillDataA { get; set; } = true; // 默认必填 public bool FillDataB { get; set; } public bool FillDataC { get; set; } } // 在Builder中添加配置转换方法 public BigObjectBuilder FromConfig(BigObjectFillConfig config) { if (config.FillDataA) WithDataA(); if (config.FillDataB) WithDataB(); if (config.FillDataC) WithDataC(); return this; } // 使用示例 var config = new BigObjectFillConfig { FillDataA = true, FillDataC = true }; var model = new BigObjectBuilder().FromConfig(config).Build(dataService);
方案优势
- 消除了原方案中大量的if判断,代码结构更清晰
- 依赖关系由Builder内部处理,调用方无需关注字段间的依赖逻辑
- 链式调用的配置方式可读性强,扩展新字段时只需添加对应的
WithXXX方法 - 可选的配置类兼容逻辑,平滑过渡原有代码
内容的提问来源于stack exchange,提问作者Kirill_Cyber
相关产品推荐
相关产品推荐

