C# .NET 6医疗评分计算:如何避免Switch语句?规则引擎替代方案
解决方案:结构化实现医疗评分计算
针对你的需求,规则设计模式完全不算过度设计——15个变量的医疗评分逻辑如果用硬编码的switch/if堆叠,会导致代码臃肿、难以维护,且医疗规则可能随指南更新而调整,结构化的实现方式能大幅提升可维护性、可测试性和扩展性。
下面提供两种适合.NET 6场景的落地方案:
方案一:策略模式+规则类封装
把每个变量的评分逻辑封装成独立的规则类,通过统一接口聚合计算,符合开闭原则,每个规则可单独测试和修改。
1. 定义规则接口
public interface IScoringRule { // 接收患者数据,返回该规则对应的分数 int CalculateScore(PatientData patientData); }
2. 实现单个变量的规则类
以射血分数为例,用C# 8的模式匹配简化判断:
public class EjectionFractionRule : IScoringRule { public int CalculateScore(PatientData patientData) { return patientData.EjectionFraction switch { < 20 => 7, >= 20 and <= 24 => 6, >= 25 and <= 29 => 5, >= 30 and <= 34 => 3, >= 35 and <= 39 => 2, >= 40 => 0, _ => 0 }; } }
你可以为年龄、肌酐等其他14个变量分别创建对应的AgeRule、CreatinineRule等类。
3. 实现评分计算器
通过依赖注入聚合所有规则,统一计算总分:
public class ScoringCalculator { private readonly IEnumerable<IScoringRule> _allRules; // 构造函数注入所有规则 public ScoringCalculator(IEnumerable<IScoringRule> allRules) { _allRules = allRules; } public int CalculateTotalScore(PatientData patientData) { // 遍历所有规则,累加分数 return _allRules.Sum(rule => rule.CalculateScore(patientData)); } }
4. 注册依赖(Program.cs)
// 注册所有规则类 builder.Services.AddScoped<IScoringRule, EjectionFractionRule>(); builder.Services.AddScoped<IScoringRule, AgeRule>(); // ... 注册剩余13个规则类 builder.Services.AddScoped<ScoringCalculator>();
方案二:配置驱动的规则计算
如果规则需要频繁调整(比如医疗指南更新),可以把区间和分数定义在配置文件中,无需修改代码即可更新规则。
1. 配置文件(appsettings.json)
"ScoringRules": { "EjectionFraction": [ {"Min": null, "Max": 19, "Score": 7}, {"Min": 20, "Max": 24, "Score": 6}, {"Min": 25, "Max": 29, "Score": 5}, {"Min": 30, "Max": 34, "Score": 3}, {"Min": 35, "Max": 39, "Score": 2}, {"Min": 40, "Max": null, "Score": 0} ], "Age": [ {"Min": null, "Max": 64, "Score": 0}, {"Min": 65, "Max": 74, "Score": 2}, {"Min": 75, "Max": null, "Score": 3} // 其他变量规则依次添加 ] }
2. 配置模型类
public class ScoringConfig { public Dictionary<string, List<RangeRule>> ScoringRules { get; set; } } public class RangeRule { public int? Min { get; set; } public int? Max { get; set; } public int Score { get; set; } }
3. 配置驱动的计算器
public class ConfigBasedScoringCalculator { private readonly ScoringConfig _config; public ConfigBasedScoringCalculator(IConfiguration config) { _config = config.GetSection("ScoringRules").Get<ScoringConfig>(); } public int CalculateTotalScore(PatientData patientData) { int total = 0; // 计算射血分数 total += GetVariableScore(patientData.EjectionFraction, "EjectionFraction"); // 计算年龄 total += GetVariableScore(patientData.Age, "Age"); // ... 处理其他13个变量 return total; } private int GetVariableScore(int value, string ruleKey) { if (!_config.ScoringRules.TryGetValue(ruleKey, out var rules)) return 0; foreach (var rule in rules) { bool isInRange = true; if (rule.Min.HasValue && value < rule.Min.Value) isInRange = false; if (rule.Max.HasValue && value > rule.Max.Value) isInRange = false; if (isInRange) return rule.Score; } return 0; } }
关于规则模式的必要性
15个变量的硬编码逻辑会导致:
- 代码冗长,单个方法可能数百行,难以定位问题
- 修改规则时容易误改其他逻辑,风险高
- 无法单独测试某个变量的评分逻辑
而规则模式(或上述两种变体)将每个变量的逻辑解耦,每个规则类/配置项独立,既便于测试,也能快速响应规则变更,完全符合医疗场景对准确性和可维护性的要求,绝非过度设计。
内容的提问来源于stack exchange,提问作者nitse
相关产品推荐
相关产品推荐

