using RobotNet.VDA5050.Type; using RobotNet10.RobotApp.Interfaces; namespace RobotNet10.RobotApp.Services.Robot.Actions; public class RobotActionProvider(Logger Logger, IServiceProvider ServiceProvider) : BackgroundService, IRobotActionProvider { public bool IsInitialized { get; private set; } private Dictionary Actions = []; public RobotAction GetRobotAction(ActionType type) { if (!Actions.TryGetValue(type, out var actionType)) { Logger.Error($"RobotAction not found for ActionType: {type}"); throw new InvalidOperationException($"RobotAction not found for ActionType: {type}"); } try { var instance = ActivatorUtilities.CreateInstance(ServiceProvider, actionType); if (instance is not RobotAction robotAction) { Logger.Error($"Type {actionType.Name} is not a RobotAction"); throw new InvalidOperationException($"Type {actionType.Name} is not a RobotAction"); } return robotAction; } catch (Exception ex) { Logger.Error($"Error creating instance of {actionType.Name}: {ex.Message}"); throw; } } private static Dictionary DiscoverActions() { var actionTypes = new Dictionary(); var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName?.StartsWith("RobotNet10.RobotApp") == true); foreach (var assembly in assemblies) { var types = assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(RobotAction))); foreach (var type in types) { var attributes = type.GetCustomAttributes(typeof(RobotActionAttribute), false); if (attributes.Length > 0) { foreach(var attribute in attributes) { if(attribute is RobotActionAttribute robotAttribute) { actionTypes[robotAttribute.ActionType] = type; break; } } } } } return actionTypes; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Yield(); try { Logger.Info("Initializing RobotActionProvider..."); Actions = DiscoverActions(); IsInitialized = true; Logger.Info($"Discovered {Actions.Count} robot actions."); } catch (Exception ex) { Logger.Warning($"Failed to discover robot actions. {ex}"); throw; } } public RobotAction[] GetRobotActions() { try { List robotActions = []; foreach (var actionType in Actions.Values) { var instance = ActivatorUtilities.CreateInstance(ServiceProvider, actionType); if (instance is not RobotAction robotAction) { Logger.Error($"Type {actionType.Name} is not a RobotAction"); throw new InvalidOperationException($"Type {actionType.Name} is not a RobotAction"); } robotActions.Add(robotAction); } return [.. robotActions]; } catch (Exception ex) { throw new Exception ($"Error get RobotActions: {ex.Message}"); } } }