Backend/e-suite.Workflow.Core/Extensions/TaskExtensions.cs
2026-01-20 21:50:10 +00:00

116 lines
3.3 KiB
C#

namespace e_suite.Workflow.Core;
//copied from Database.core.
public class TaskDefinition
{
public string Type { get; set; } = string.Empty;
public int Order { get; set; }
public Dictionary<string, object>? Config { get; set; }
}
public static class TaskExtensions
{
public static TaskDefinition ToDefinition(this ITask task, int order)
{
if (task is ITemplateValidatable v)
{
var errors = v.ValidateForTemplate().ToList();
if (errors.Any())
throw new InvalidOperationException(
$"Task {task.GetType().Name} is invalid: {string.Join("; ", errors)}");
}
return new TaskDefinition
{
Type = task.GetType().AssemblyQualifiedName!,
Order = order,
Config = ExtractConfig(task)
};
}
private static Dictionary<string, object> ExtractConfig(object task)
{
var dict = new Dictionary<string, object>();
foreach (var prop in task.GetType().GetProperties())
{
if (!prop.CanRead) continue;
if (prop.GetIndexParameters().Length > 0) continue; // skip indexers
if (prop.IsDefined(typeof(RuntimeOnlyAttribute), inherit: true))
continue;
var value = prop.GetValue(task);
if (value != null)
dict[prop.Name] = value;
}
return dict;
}
public static ITask ToTask(this TaskDefinition def)
{
var type = Type.GetType(def.Type, throwOnError: true)!;
var task = (ITask)Activator.CreateInstance(type)!;
foreach (var kvp in def.Config)
{
var prop = type.GetProperty(kvp.Key);
if (prop == null || !prop.CanWrite) continue;
if (prop.IsDefined(typeof(RuntimeOnlyAttribute), inherit: true))
continue;
object? converted = ConvertValue(kvp.Value, prop.PropertyType);
prop.SetValue(task, converted);
}
if (task is ITemplateValidatable v)
{
var errors = v.ValidateForTemplate().ToList();
if (errors.Any())
throw new InvalidOperationException(
$"Task {task.GetType().Name} is invalid: {string.Join("; ", errors)}");
}
return task;
}
private static object? ConvertValue(object? value, Type targetType)
{
if (value == null) return null;
// Handle enums
if (targetType.IsEnum)
return Enum.Parse(targetType, value.ToString()!);
// Handle Guid
if (targetType == typeof(Guid))
return Guid.Parse(value.ToString()!);
// Handle nullable types
var underlying = Nullable.GetUnderlyingType(targetType);
if (underlying != null)
return Convert.ChangeType(value, underlying);
return Convert.ChangeType(value, targetType);
}
public static bool IsCompleted(this ITask task)
{
return task.TaskState.In(TaskState.Completed, TaskState.Cancelled);
}
public static bool ReadyToActivate(this ITask task)
{
foreach (var predecessor in task.Predecessors)
{
if (!predecessor.IsCompleted())
{
return false;
}
}
return true;
}
}