C#如何匹配不同类的泛型类型并校验能力是否满足对应需求
前置修复说明
你现有代码存在两个需要先调整的小问题:
SetCapability<T>未实现ICapability接口,无法存入List<ICapability>集合,需要先补上继承关系- 区间比较需要泛型参数
T支持大小比较,建议给RangeCapability<T>加上IComparable<T>的泛型约束
方案1:校验逻辑下沉到能力类(推荐,符合开闭原则)
直接在ICapability接口中定义校验契约,每个具体能力类自行实现类型匹配、值校验逻辑,上层无需关心泛型匹配的细节。
public interface ICapability { public string Name { get; } // 新增校验方法契约 bool IsMatch(IRequirement requirement); } // Range能力实现 public class RangeCapability<T> : ICapability where T : IComparable<T> { public string Name { get; set; } public T Min { get; set; } public T Max { get; set; } public bool IsMatch(IRequirement requirement) { // 先匹配泛型需求类型 if (requirement is not Requirement<T> req) return false; // 校验区间 return req.Value.CompareTo(Min) >= 0 && req.Value.CompareTo(Max) <= 0; } } // Set能力实现,补上ICapability继承 public class SetCapability<T> : ICapability { public string Name { get; set; } public HashSet<T> Set { get; set; } public bool IsMatch(IRequirement requirement) { if (requirement is not Requirement<T> req) return false; return Set.Contains(req.Value); } }
Entity的校验逻辑可以简化为:
public class Entity { public List<ICapability> Capabilities { get; set; } = new(); public bool IsSatisfying(List<IRequirement> requirements) { foreach (var requirement in requirements) { var capability = Capabilities.FirstOrDefault(x => x.Name == requirement.Name); // 找不到对应能力/校验不通过直接返回不满足 if (capability == null || !capability.IsMatch(requirement)) return false; } return true; } }
该方案后续新增能力类型只要实现IsMatch方法即可,上层校验逻辑完全不需要修改,扩展性更强。
方案2:不改现有接口定义,用动态分派实现
如果你不能修改ICapability和能力类的原有定义,可以用运行时动态重载匹配来处理泛型类型的校验:
public class Entity { public List<ICapability> Capabilities { get; set; } = new(); public bool IsSatisfying(List<IRequirement> requirements) { foreach (var requirement in requirements) { var capability = Capabilities.FirstOrDefault(x => x.Name == requirement.Name); if (capability == null) return false; // 动态分派,运行时自动匹配对应泛型类型的校验重载 if (!CheckMatch(capability as dynamic, requirement as dynamic)) return false; } return true; } // 泛型Range校验重载 private bool CheckMatch<T>(RangeCapability<T> cap, Requirement<T> req) where T : IComparable<T> { return req.Value.CompareTo(cap.Min) >= 0 && req.Value.CompareTo(cap.Max) <= 0; } // 泛型Set校验重载 private bool CheckMatch<T>(SetCapability<T> cap, Requirement<T> req) { return cap.Set.Contains(req.Value); } // 类型不匹配时的兜底重载 private bool CheckMatch(object cap, object req) { // 泛型类型不匹配,返回校验失败 return false; } }
该方案依赖运行时动态类型解析,性能比方案1略低,适合小范围使用的场景。
补充说明
两种方案默认都是严格匹配泛型类型,比如RangeCapability<int>和Requirement<long>就算数值范围符合也会判定为类型不匹配,如果你需要支持兼容数值类型转换,可以在校验逻辑里额外加类型转换处理。找不到同名能力时的处理逻辑也可以按业务需求调整,比如部分场景不需要所有需求都有对应能力,可以跳过校验返回true。
内容的提问来源于stack exchange,提问作者GUZ
相关产品推荐
相关产品推荐

