using DS.Module.Core.Data; namespace DS.Module.Core.Condition { public class ConditionHelper { /// /// 根据ContitionContent条件,从数据上下文TaskFlowDataContext中取出指定数据,然后判断条件是否符合 /// public static bool IsPass(ConditionContent conditionContent, TaskFlowDataContext dataContext) { bool? thisScopeResult = null; if (conditionContent == null || conditionContent.Conditions == null || conditionContent.Conditions.Count == 0) { return true; } IDictionary? dataDic = null; if (!string.IsNullOrEmpty(conditionContent.SourceName) && dataContext.ContainsKey(conditionContent.SourceName)) { dataDic = dataContext[conditionContent.SourceName] as IDictionary; } foreach (var item in conditionContent.Conditions) { var itemResult = false; string? valStr = null; if (dataDic != null && dataDic.TryGetValue(item.Field, out object? objVal)) { valStr = objVal?.ToString(); } else if (dataContext.ContainsKey(item.Field)) { var obj = dataContext.Get(item.Field)!; valStr = obj.ToString(); } else if (item.Field!.Contains('.')) { var firstKey = item.Field.Split('.').First(); if (dataContext.ContainsKey(firstKey)) { var obj = dataContext.Get(firstKey)!; var propertyPath = item.Field.Substring(item.Field.IndexOf('.') + 1); var (_, val, _) = GetPropertyValue(obj, propertyPath); if (val != null) valStr = val.ToString(); } } switch (item.Operator) { case "equal": itemResult = valStr?.Equals(item.Value, StringComparison.OrdinalIgnoreCase) == true; break; case "not_equal": itemResult = valStr?.Equals(item.Value, StringComparison.OrdinalIgnoreCase) != true; break; case "contains": itemResult = valStr?.Contains(item.Value, StringComparison.OrdinalIgnoreCase) == true; break; case "not_contain": itemResult = valStr?.Contains(item.Value, StringComparison.OrdinalIgnoreCase) != true; break; case "start_with": itemResult = valStr?.StartsWith(item.Value, StringComparison.OrdinalIgnoreCase) == true; break; case "end_with": itemResult = valStr?.EndsWith(item.Value, StringComparison.OrdinalIgnoreCase) == true; break; case "greater_than": { itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 > temp2; break; } case "greater_than_or_equal": { itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 >= temp2; break; } case "less_than": { itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 < temp2; break; } case "less_than_or_equal": { itemResult = double.TryParse(valStr, out double temp1) && double.TryParse(item.Value, out double temp2) && temp1 <= temp2; break; } } if (thisScopeResult == null) { thisScopeResult = itemResult; } else { if (conditionContent.LogicalOperator == "and") { thisScopeResult = thisScopeResult.Value && itemResult; } else if (conditionContent.LogicalOperator == "or") { thisScopeResult = thisScopeResult.Value || itemResult; } } } //thisScopeResult ??= true; // 实际这里的thisScopeResult的值啃腚不为null if (conditionContent.Groups != null && conditionContent.Groups.Count > 0) { // 组的结果 var groupResult = new List(); foreach (var item in conditionContent.Groups) { // 递归调用,向组里添加结果 groupResult.Add(IsPass(item, dataContext)); } if (conditionContent.LogicalOperator == "and") { return thisScopeResult == true && groupResult.All(a => a); } else if (conditionContent.LogicalOperator == "or") { return thisScopeResult == true || groupResult.Any(a => a); } } return thisScopeResult == true; } /// /// 深度获取对象属性值 /// /// 对象 /// 属性路径 static (bool isOk, object? val, string? otherPropertyPath) GetPropertyValue(object obj, string propertyPath) { var propertyName = propertyPath.Split('.').FirstOrDefault(); var type = obj.GetType(); var property = type.GetProperty(propertyName); if (property == null) { return (true, null, null); } if (property.PropertyType.IsClass && property.PropertyType != typeof(string)) { var val = property.GetValue(obj); if (val == null) { return (true, null, null); } var otherPropertyPath = propertyPath.Substring(propertyPath.IndexOf('.') + 1); return GetPropertyValue(val, otherPropertyPath); } else { var val = property.GetValue(obj); return (true, val, null); } } } }