Skip to content

Commit c46ca67

Browse files
authored
Implemented Auto-Data Conversion
1 parent 2bc38a5 commit c46ca67

File tree

5 files changed

+1776
-702
lines changed

5 files changed

+1776
-702
lines changed
Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,46 @@
11
using System;
2+
using System.Globalization;
3+
using System.Linq;
24

35
public static class CommandParser
46
{
5-
public static void Parse(string rawInput, out string command, out string[] args)
6-
{
7-
if (string.IsNullOrWhiteSpace(rawInput))
8-
{
9-
command = "";
10-
args = Array.Empty<string>();
11-
return;
12-
}
13-
14-
int idx = rawInput.IndexOf(' ');
15-
if (idx < 0)
16-
{
17-
command = rawInput;
18-
args = Array.Empty<string>();
19-
}
20-
else
21-
{
22-
command = rawInput.Substring(0, idx);
23-
var rest = rawInput.Substring(idx + 1);
24-
25-
args = rest.Split(new[]{' '}, StringSplitOptions.RemoveEmptyEntries);
26-
}
7+
public static void StringToCommand(string rawInput, out string command, out string[] args)
8+
{
9+
// TODO: Keep in single string when surrounded in quotes
10+
var parts = rawInput.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
11+
if (parts.Length == 0)
12+
{
13+
command = "";
14+
args = Array.Empty<string>();
15+
return;
16+
}
17+
18+
// Return variables
19+
command = parts[0];
20+
args = parts.Length > 1? parts.Skip(1).ToArray() : Array.Empty<string>();
21+
}
22+
23+
// Convert string into it's given type. E.g "1" = int, "STATE_IDLE" = enum, etc...
24+
public static object ConvertStringToType(string raw, Type targetType)
25+
{
26+
// String Conversion
27+
if (targetType == typeof(string))
28+
{
29+
return raw;
30+
}
31+
32+
// Enum Conversion
33+
if (targetType.IsEnum)
34+
{
35+
return Enum.Parse(targetType, raw, ignoreCase: true);
36+
}
37+
38+
// IConvertible Primitive Converison
39+
if (typeof(IConvertible).IsAssignableFrom(targetType))
40+
{
41+
return Convert.ChangeType(raw, targetType, CultureInfo.InvariantCulture);
42+
}
43+
44+
throw new InvalidOperationException($"No converter for type {targetType.Name}");
2745
}
2846
}

Commander/Runtime/Core/CommandRegistry.cs

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public static class CommandRegistry
2323

2424
#endregion
2525

26-
#region Methods
26+
#region Lifecycle
2727

2828
/// <summary>
2929
/// Register given MonoBehaviour's methods as commands.
@@ -71,39 +71,79 @@ public static void RegisterCommand(MonoBehaviour target)
7171
// Log the registration of commands
7272
Debug.Log($"[CommandRegistry] Registered {target.GetType().Name} with {_commands.Count} methods.");
7373
}
74-
}
75-
76-
public static void ExecuteCommand(string commandName, params object[] parameters)
77-
{
78-
if (_commands.TryGetValue(commandName, out var list))
79-
{
80-
foreach (var (mi, target) in list)
81-
{
82-
try
83-
{
84-
mi.Invoke(target, parameters);
85-
}
86-
catch (Exception ex)
87-
{
88-
Debug.LogError($"Error executing command '{commandName}': {ex.Message}");
89-
}
90-
}
91-
}
92-
else
93-
{
94-
Debug.LogWarning($"Command '{commandName}' not found.");
95-
}
96-
}
97-
74+
}
75+
9876
public static void ClearCommands()
9977
{
10078
_commands.Clear();
10179
if (ShowDebugLogs)
10280
{
10381
Debug.Log("[CommandRegistry] Cleared all commands.");
10482
}
105-
}
106-
83+
}
84+
10785
#endregion
108-
}
86+
87+
#region Command Execution
88+
89+
public static void ExecuteCommand(string commandInput)
90+
{
91+
CommandParser.StringToCommand(commandInput, out string command, out string[] arguments);
92+
ExecuteCommand(command, arguments);
93+
}
94+
95+
private static void ExecuteCommand(string commandName, string[] rawArgs)
96+
{
97+
if (!_commands.TryGetValue(commandName, out var entries))
98+
{
99+
Debug.LogWarning($"Command '{commandName}' not found.");
100+
return;
101+
}
102+
103+
foreach (var (mi, target) in entries)
104+
{
105+
var paramInfos = mi.GetParameters();
106+
if (paramInfos.Length != rawArgs.Length)
107+
{
108+
Debug.LogError($"Command '{commandName}' expects {paramInfos.Length} args, got {rawArgs.Length}");
109+
continue;
110+
}
111+
112+
var converted = new object[rawArgs.Length];
113+
bool conversionFailed = false;
114+
for (int i = 0; i < rawArgs.Length; i++)
115+
{
116+
var t = paramInfos[i].ParameterType;
117+
try
118+
{
119+
converted[i] = CommandParser.ConvertStringToType(rawArgs[i], t);
120+
}
121+
catch (Exception e)
122+
{
123+
Debug.LogError(
124+
$"Command '{commandName}': failed to convert \"{rawArgs[i]}\" to {t.Name}: {e.Message}");
125+
conversionFailed = true;
126+
break;
127+
}
128+
}
129+
130+
if (conversionFailed)
131+
{
132+
continue;
133+
}
134+
135+
try
136+
{
137+
mi.Invoke(target, converted);
138+
}
139+
catch (Exception ex)
140+
{
141+
Debug.LogError(
142+
$"Error executing '{commandName}': {ex.InnerException?.Message ?? ex.Message}");
143+
}
144+
}
145+
}
146+
}
147+
148+
#endregion
109149
}

0 commit comments

Comments
 (0)