using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; namespace Parsing { public static class ConditionDelegateFactory { // 正则表达式用于解析函数名和参数 private static readonly Regex _methodCallRegex = new Regex( @"^(?[a-zA-Z_][a-zA-Z0-9_]*)(?:\((?.*)\))?$", RegexOptions.Compiled ); /// /// 解析条件字符串并创建 Func 委托。 /// /// 条件字符串,如 "EntityHealth(20)" 或 "IsTargetAlive"。 /// 实体类型,通常是 typeof(Entity.Entity)。 /// 包含条件静态方法的类类型,如 typeof(ConditionFunctions)。 /// 一个 Func 委托。 /// 当条件字符串格式不正确时抛出。 /// 当找不到匹配的条件方法时抛出。 public static Func CreateConditionDelegate( string conditionString, Type entityType, Type conditionClassType) { if (string.IsNullOrWhiteSpace(conditionString)) throw new ArgumentException("条件字符串不能为空。", nameof(conditionString)); if (entityType == null) throw new ArgumentNullException(nameof(entityType)); if (conditionClassType == null) throw new ArgumentNullException(nameof(conditionClassType)); var match = _methodCallRegex.Match(conditionString); if (!match.Success) { throw new ArgumentException( $"条件字符串 '{conditionString}' 格式不正确。期望格式: MethodName 或 MethodName(arg1, arg2)。"); } var methodName = match.Groups["methodName"].Value; var argsString = match.Groups["args"].Success ? match.Groups["args"].Value : null; // 逻辑修改:支持多参数解析 var parsedArgValues = new List(); // 存储解析后的参数值 var parsedArgTypes = new List(); // 存储解析后的参数类型 // 第一个参数始终是实体类型 parsedArgTypes.Add(entityType); if (!string.IsNullOrEmpty(argsString)) { // 使用辅助方法拆分参数字符串 var argStrings = SplitArguments(argsString); // <-- 新增辅助方法调用 foreach (var argStr in argStrings) { var arg = ParseLiteral(argStr.Trim()); parsedArgValues.Add(arg.value); parsedArgTypes.Add(arg.type); } } // 逻辑修改:更健壮的方法查找和参数类型匹配 MethodInfo bestMatchMethod = null; object[] finalInvokeArgs = null; // 存储最终用于 Invoke 的参数值(已转换类型) // 获取所有静态、公共或非公共的同名方法,并过滤返回类型为 bool 的 var methods = conditionClassType .GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .Where(m => m.Name == methodName && m.ReturnType == typeof(bool)) .ToList(); foreach (var method in methods) { var parameters = method.GetParameters(); // 检查参数数量是否匹配 if (parameters.Length != parsedArgTypes.Count) continue; var paramsMatch = true; var currentInvokeArgs = new object[parameters.Length]; // 临时存储当前方法的参数值 // 检查第一个参数(实体类型) if (!parameters[0].ParameterType.IsAssignableFrom(entityType)) { paramsMatch = false; continue; } // 注意:currentInvokeArgs[0] 在这里不赋值,它将在委托执行时由传入的 entity 填充。 // 检查后续参数(解析出的额外参数) for (var i = 1; i < parameters.Length; i++) { var methodParamType = parameters[i].ParameterType; var parsedValueType = parsedArgTypes[i]; var parsedValue = parsedArgValues[i - 1]; // parsedArgValues 从索引0开始对应第一个额外参数 // 尝试直接赋值 if (methodParamType.IsInstanceOfType(parsedValue)) { currentInvokeArgs[i] = parsedValue; } // 尝试类型转换(例如 int 到 long,float 到 double) else if (CanConvert(parsedValue, methodParamType)) // <-- 新增辅助方法调用 { try { currentInvokeArgs[i] = Convert.ChangeType(parsedValue, methodParamType); } catch (Exception) // 捕获所有转换异常 { paramsMatch = false; break; } } else { paramsMatch = false; break; } } if (paramsMatch) { bestMatchMethod = method; finalInvokeArgs = currentInvokeArgs; // 存储已转换的参数值 break; // 找到第一个匹配项即停止,如果需要更复杂的匹配规则(如最具体匹配),则需要进一步处理 } } if (bestMatchMethod == null) { // 如果没有找到匹配的方法,抛出异常 var expectedSignature = $"{methodName}({string.Join(", ", parsedArgTypes.Select(t => t.Name))})"; throw new MissingMethodException( $"在类 '{conditionClassType.FullName}' 中未找到名为 '{methodName}' 的静态方法," + $"其签名与期望的 '{expectedSignature}' 且返回类型为 'bool' 不兼容。" ); } // 如果没有额外参数,直接创建委托以获得最佳性能 if (parsedArgValues.Count == 0) { return (Func)Delegate.CreateDelegate(typeof(Func), bestMatchMethod); } else { // 创建一个闭包来绑定解析后的参数 // 闭包捕获 finalInvokeArgs,并在运行时填充第一个参数 (entity) return (entity) => { // 复制一份 finalInvokeArgs,因为 Invoke 会修改数组内容(如果参数是 ref/out) // 并且需要将 entity 放入第一个位置 var invokeArgs = new object[finalInvokeArgs.Length]; invokeArgs[0] = entity; for (var i = 1; i < finalInvokeArgs.Length; i++) { invokeArgs[i] = finalInvokeArgs[i]; } return (bool)bestMatchMethod.Invoke(null, invokeArgs); }; } } /// /// 辅助方法:拆分参数字符串。 /// 这是一个更健壮的实现,能够正确处理包含逗号的带引号字符串和嵌套括号。 /// /// 待拆分的参数字符串。 /// 拆分后的参数列表。 private static IEnumerable SplitArguments(string argsString) { if (string.IsNullOrEmpty(argsString)) { return Enumerable.Empty(); } var arguments = new List(); var currentArgument = new StringBuilder(); var inQuote = false; // 跟踪是否在双引号内部 var parenLevel = 0; // 跟踪括号的嵌套层级 for (var i = 0; i < argsString.Length; i++) { var c = argsString[i]; if (c == '"') { inQuote = !inQuote; // 切换引号状态 currentArgument.Append(c); // 将引号字符保留在参数中 } else if (c == '(') { parenLevel++; // 增加括号层级 currentArgument.Append(c); } else if (c == ')') { parenLevel--; // 减少括号层级 currentArgument.Append(c); } else if (c == ',' && !inQuote && parenLevel == 0) { // 发现一个顶级的逗号分隔符:不在引号内,也不在任何括号内 var arg = currentArgument.ToString().Trim(); if (!string.IsNullOrEmpty(arg)) { arguments.Add(arg); } currentArgument.Clear(); // 重置,开始收集下一个参数 } else { // 其他字符,直接添加到当前参数 currentArgument.Append(c); } } // 循环结束后,添加最后一个参数(如果有的话) var lastArg = currentArgument.ToString().Trim(); if (!string.IsNullOrEmpty(lastArg)) { arguments.Add(lastArg); } return arguments; } /// /// 辅助方法:检查一个值是否可以转换为目标类型。 /// private static bool CanConvert(object value, Type targetType) { // 逻辑修改:新增辅助方法,用于检查类型转换可行性 if (value == null) return !targetType.IsValueType || (Nullable.GetUnderlyingType(targetType) != null); if (targetType.IsInstanceOfType(value)) return true; try { // 尝试转换,如果成功则表示可转换 Convert.ChangeType(value, targetType); return true; } catch (Exception) // 捕获所有可能的转换异常 { return false; } } /// /// 解析字符串字面量为对应的对象和类型。 /// 支持 int, long, float, double, bool, string。 /// /// 要解析的字面量字符串。 /// 包含解析后的值和类型的元组。 private static (object value, Type type) ParseLiteral(string literalString) { // 逻辑修改:增强 ParseLiteral,增加对 long 和 double 的支持 // 顺序很重要:先尝试更窄的类型,再尝试更宽的类型,以避免不必要的类型提升。 // 尝试解析为 int if (int.TryParse(literalString, out var intValue)) { return (intValue, typeof(int)); } // 尝试解析为 long if (long.TryParse(literalString, out var longValue)) { return (longValue, typeof(long)); } // 尝试解析为 float if (float.TryParse(literalString, out var floatValue)) { return (floatValue, typeof(float)); } // 尝试解析为 double if (double.TryParse(literalString, out var doubleValue)) { return (doubleValue, typeof(double)); } // 尝试解析为 bool if (bool.TryParse(literalString, out var boolValue)) { return (boolValue, typeof(bool)); } // 尝试解析为 string (如果被双引号包围) if (literalString.StartsWith("\"") && literalString.EndsWith("\"") && literalString.Length > 1) { return (literalString.Substring(1, literalString.Length - 2), typeof(string)); } // 默认作为字符串处理 return (literalString, typeof(string)); } } }