C#同名字符串扩展方法能否基于语法自动路由至对应实现?
实现方案说明
.NET 本身没有内置类似 [RequiresSyntax(...)] 的属性来自动路由同名扩展方法,但可以通过两种方式实现你想要的逻辑分离+自动匹配调用的需求:
方案一:自定义属性+反射路由(接近你设想的属性标记方式)
通过自定义属性标记各扩展方法对应的正则规则,再写一个统一的入口方法,在运行时通过反射匹配规则并调用对应方法。
1. 定义标记属性
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class RequiresSyntaxAttribute : Attribute { public string RegexPattern { get; } public RequiresSyntaxAttribute(string regexPattern) { RegexPattern = regexPattern; } }
2. 编写分离的逻辑类
分别在不同静态类中实现对应格式的比较逻辑:
public static class VersionsExtensions { [RequiresSyntax(@"^([A-Z]\d{2}!\[A-Z]{2}\d|[A-Z]{3})$")] public static bool IsHigher(this string source, string target) { // 版本字符串的具体比较逻辑,示例为字典序,可按需修改 return string.Compare(source, target, StringComparison.Ordinal) > 0; } } public static class IssuesExtensions { [RequiresSyntax(@"^\d{3}$")] public static bool IsHigher(this string source, string target) { // 工单编号的具体比较逻辑 return int.Parse(source) > int.Parse(target); } }
3. 实现路由入口方法
写一个统一的扩展方法作为入口,负责匹配规则并调用对应逻辑:
public static class StringSyntaxRouter { // 缓存规则与方法映射,避免重复反射扫描 private static readonly List<(Regex Regex, MethodInfo Method)> _syntaxMethods; static StringSyntaxRouter() { // 扫描所有标记了RequiresSyntaxAttribute的静态方法 _syntaxMethods = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .Where(t => t.IsStatic) .SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.Static)) .Where(m => m.GetCustomAttribute<RequiresSyntaxAttribute>() != null) .Select(m => { var attr = m.GetCustomAttribute<RequiresSyntaxAttribute>(); return (Regex: new Regex(attr.RegexPattern, RegexOptions.Compiled), Method: m); }) .ToList(); } public static bool IsHigher(this string source, string target) { if (source == null || target == null) throw new ArgumentNullException(); // 匹配source对应的规则方法 var matched = _syntaxMethods.FirstOrDefault(s => s.Regex.IsMatch(source)); if (matched.Method == null) throw new InvalidOperationException("未找到匹配的语法规则方法"); // 验证target格式与source一致(可根据需求调整是否需要此校验) if (!matched.Regex.IsMatch(target)) throw new ArgumentException("目标字符串格式与源字符串不匹配"); // 调用对应逻辑方法 return (bool)matched.Method.Invoke(null, new object[] { source, target }); } // 同理实现IsLower方法 public static bool IsLower(this string source, string target) { var isHigher = source.IsHigher(target); return !isHigher && !string.Equals(source, target); } }
方案二:模式匹配+轻量路由(性能更优)
如果不想用反射,可在入口方法中通过预编译的正则做格式判断,直接调用对应静态类的逻辑,既保持逻辑分离,又避免反射开销:
public static class StringComparisonExtensions { // 预编译正则,提升匹配性能 private static readonly Regex _versionRegex = new Regex(@"^([A-Z]\d{2}!\[A-Z]{2}\d|[A-Z]{3})$", RegexOptions.Compiled); private static readonly Regex _issueRegex = new Regex(@"^\d{3}$", RegexOptions.Compiled); public static bool IsHigher(this string source, string target) { if (_versionRegex.IsMatch(source) && _versionRegex.IsMatch(target)) return VersionsExtensions.IsHigher(source, target); if (_issueRegex.IsMatch(source) && _issueRegex.IsMatch(target)) return IssuesExtensions.IsHigher(source, target); throw new InvalidOperationException("不支持的字符串格式"); } public static bool IsLower(this string source, string target) { if (_versionRegex.IsMatch(source) && _versionRegex.IsMatch(target)) return !VersionsExtensions.IsHigher(source, target) && !string.Equals(source, target); if (_issueRegex.IsMatch(source) && _issueRegex.IsMatch(target)) return !IssuesExtensions.IsHigher(source, target) && !string.Equals(source, target); throw new InvalidOperationException("不支持的字符串格式"); } }
调用方式
两种方案都支持你想要的调用形式:
// 调用版本字符串比较 "A00".IsLower("B00"); // 调用工单编号比较 "001".IsLower("002");
内容的提问来源于stack exchange,提问作者Ludovic Wagner
相关产品推荐
相关产品推荐

