向宁 fc4ecbbacc feat: add gRPC auth, condition comparators, seed data, EF migrations
- gRPC auth service for token validation
- Value comparator system (string, numeric, boolean, datetime, collection)
- Condition evaluator with strategy chain
- Form definition and data improvements
- Workflow instance/task endpoints updated
- Seed data and EF design-time factory
- Test coverage for comparators and handlers
2026-05-20 20:28:35 +08:00

134 lines
4.5 KiB
C#

using System.Globalization;
using System.Text.Json;
namespace Workflow.Domain.Expressions.Comparators;
/// <summary>
/// 值对比器共享的静态工具方法。从 ConditionEvaluator 中提取,
/// 供所有内置对比器复用。
/// </summary>
public static class ValueComparatorHelper
{
public static bool TryGetDecimal(object? value, out decimal result)
{
result = 0m;
return value switch
{
decimal d => SetResult(d, out result),
double db => SetResult((decimal)db, out result),
float f => SetResult((decimal)f, out result),
int i => SetResult((decimal)i, out result),
long l => SetResult((decimal)l, out result),
short s => SetResult((decimal)s, out result),
byte b => SetResult((decimal)b, out result),
uint ui => SetResult((decimal)ui, out result),
ulong ul => SetResult((decimal)ul, out result),
string str => decimal.TryParse(str, out result),
JsonElement e => TryGetDecimalFromElement(e, out result),
_ => false
};
}
public static bool TryGetDecimalFromElement(JsonElement element, out decimal result)
{
result = 0m;
if (element.ValueKind == JsonValueKind.Number)
return element.TryGetDecimal(out result);
if (element.ValueKind == JsonValueKind.String)
{
var str = element.GetString();
return str is not null && decimal.TryParse(str, out result);
}
return false;
}
public static bool TryGetDateTime(object? value, out DateTime result)
{
result = DateTime.MinValue;
return value switch
{
DateTime dt => SetResult(dt, out result),
DateTimeOffset dto => SetResult(dto.UtcDateTime, out result),
string s => DateTime.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result),
JsonElement e => TryGetDateTimeFromElement(e, out result),
_ => false
};
}
public static bool TryGetDateTimeFromElement(JsonElement element, out DateTime result)
{
result = DateTime.MinValue;
if (element.ValueKind == JsonValueKind.String)
{
var str = element.GetString();
return str is not null && DateTime.TryParse(str, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result);
}
return false;
}
public static bool TryGetBoolean(object? value, out bool result)
{
result = false;
return value switch
{
bool b => SetResult(b, out result),
string s => bool.TryParse(s, out result),
JsonElement e => TryGetBooleanFromElement(e, out result),
_ => false
};
}
public static bool TryGetBooleanFromElement(JsonElement element, out bool result)
{
result = false;
if (element.ValueKind == JsonValueKind.True) { result = true; return true; }
if (element.ValueKind == JsonValueKind.False) { result = false; return true; }
if (element.ValueKind == JsonValueKind.String)
{
var str = element.GetString();
return str is not null && bool.TryParse(str, out result);
}
return false;
}
public static string? GetStringValue(object? value)
{
return value switch
{
null => null,
string s => s,
JsonElement e => e.ValueKind == JsonValueKind.String ? e.GetString() : e.GetRawText(),
_ => value.ToString()
};
}
public static bool TryGetDecimalFromCondition(object? conditionValue, out decimal result)
{
if (conditionValue is string s)
return decimal.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out result);
return TryGetDecimal(conditionValue, out result);
}
public static bool TryGetDateTimeFromCondition(object? conditionValue, out DateTime result)
{
if (conditionValue is string s)
return DateTime.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result);
return TryGetDateTime(conditionValue, out result);
}
public static bool TryGetBooleanFromCondition(object? conditionValue, out bool result)
{
if (conditionValue is string s)
return bool.TryParse(s, out result);
return TryGetBoolean(conditionValue, out result);
}
private static bool SetResult<T>(T value, out T result)
{
result = value;
return true;
}
}