|
|
|
|
using DS.Module.Core.Data;
|
|
|
|
|
|
|
|
|
|
namespace DS.Module.Core.Condition
|
|
|
|
|
{
|
|
|
|
|
public class ConditionHelper
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据ContitionContent条件,从数据上下文TaskFlowDataContext中取出指定数据,然后判断条件是否符合
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool IsPass(ConditionContent conditionContent, TaskFlowDataContext dataContext)
|
|
|
|
|
{
|
|
|
|
|
bool? thisScopeResult = null;
|
|
|
|
|
|
|
|
|
|
if (conditionContent == null || conditionContent.Conditions == null || conditionContent.Conditions.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IDictionary<string, object>? dataDic = null;
|
|
|
|
|
if (!string.IsNullOrEmpty(conditionContent.SourceName) && dataContext.ContainsKey(conditionContent.SourceName))
|
|
|
|
|
{
|
|
|
|
|
dataDic = dataContext[conditionContent.SourceName] as IDictionary<string, object>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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<object>(item.Field)!;
|
|
|
|
|
valStr = obj.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (item.Field!.Contains('.'))
|
|
|
|
|
{
|
|
|
|
|
var firstKey = item.Field.Split('.').First();
|
|
|
|
|
|
|
|
|
|
if (dataContext.ContainsKey(firstKey))
|
|
|
|
|
{
|
|
|
|
|
var obj = dataContext.Get<object>(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<bool>();
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 深度获取对象属性值
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="obj">对象</param>
|
|
|
|
|
/// <param name="propertyPath">属性路径</param>
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|