Backend/e-suite.Workflow.Core/Extensions/TaskExtensions.cs

207 lines
6.4 KiB
C#

using e_suite.Database.Core.Models;
using e_suite.Database.Core.Tables.Contacts;
using e_suite.Database.Core.Tables.Domain;
using e_suite.Workflow.Core.Attributes;
using e_suite.Workflow.Core.Interfaces;
using eSuite.Core.Miscellaneous;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace e_suite.Workflow.Core.Extensions;
public static class TaskExtensions
{
private static Dictionary<string, object?> ToConfigDictionary(this ITask task)
{
var dictionary = new Dictionary<string, object?>();
var type = task.GetType();
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in properties)
{
if (!prop.CanRead)
continue;
if (!prop.CanWrite)
continue;
var value = prop.GetValue(task);
dictionary[prop.Name] = value;
}
return dictionary;
}
public static ITask ToTask(this TaskDefinition definition, JsonSerializerOptions jsonSerializerOptions)
{
var type = Type.GetType(definition.Type);
if (type == null)
throw new InvalidOperationException($"Unknown task type '{definition.Type}'.");
var instance = Activator.CreateInstance(type) as ITask;
if (instance == null)
throw new InvalidOperationException($"Type '{definition.Type}' does not implement ITask.");
FromConfigDictionary(instance, definition.Config, jsonSerializerOptions);
return instance;
}
public static void FromConfigDictionary(this object obj, Dictionary<string, object?> dict, JsonSerializerOptions jsonSerializerOptions)
{
var type = obj.GetType();
foreach (var kvp in dict)
{
var prop = type.GetProperty(
kvp.Key,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase
);
if (prop == null || !prop.CanWrite)
continue;
var targetType = prop.PropertyType;
var value = kvp.Value;
// If the value is a JsonElement, convert it to the target type
if (value is JsonElement je)
{
if (targetType.IsEnum)
{
// Enums come through as strings
value = Enum.Parse(targetType, je.GetString()!, ignoreCase: true);
}
else
{
// Deserialize JSON into the target type (handles lists, objects, primitives)
value = JsonSerializer.Deserialize(je.GetRawText(), targetType, jsonSerializerOptions);
}
}
prop.SetValue(obj, value);
}
}
public static TaskDefinition ToDefinition(this ITask task)
{
if (task is null)
throw new NullReferenceException();
return new TaskDefinition
{
Type = task.GetType().FullName,
Config = task.ToConfigDictionary()
};
}
//public static TaskDefinition ToDefinition(this ITask task)
//{
// if (task is ITemplateValidatable v)
// {
// var errors = v.ValidateForTemplate().ToList();
// if (errors.Count != 0)
// throw new InvalidOperationException(
// $"Task {task.GetType().Name} is invalid: {string.Join("; ", errors)}");
// }
// return new TaskDefinition
// {
// Type = task.GetType().FullName!,
// 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)!;
// if (def.Config != null)
// 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.Count != 0)
// 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);
//}
//Todo can only be on a run-time instance
//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;
//}
}