|
2 | 2 | using System.Collections.Generic; |
3 | 3 | using System.Reflection; |
4 | 4 |
|
5 | | -namespace NetLeaf.Bridge |
| 5 | +namespace NetLeaf.Bridge; |
| 6 | + |
| 7 | +/// <summary> |
| 8 | +/// Management of class instances. |
| 9 | +/// </summary> |
| 10 | +public static class InstanceFactory |
6 | 11 | { |
| 12 | + // Map C++ IDs to Class Instances |
| 13 | + // TODO: Check if we can replace a uint handle with IntPtr to C++ Class? |
| 14 | + private static Dictionary<uint, object> instanceMap = new Dictionary<uint, object>(); |
| 15 | + private static uint currentID = 0; |
| 16 | + |
7 | 17 | /// <summary> |
8 | | - /// Management of class instances. |
| 18 | + /// Create a class instance from its type. |
9 | 19 | /// </summary> |
10 | | - public static class InstanceFactory |
| 20 | + /// <param name="typeNamespace">Type to instantiate.</param> |
| 21 | + /// <returns>ID/Handle.</returns> |
| 22 | + public static uint CreateInstance(string typeNamespace) |
11 | 23 | { |
12 | | - // Map C++ IDs to Class Instances |
13 | | - // TODO: Check if we can replace a uint handle with IntPtr to C++ Class? |
14 | | - private static Dictionary<uint, object> instanceMap = new Dictionary<uint, object>(); |
15 | | - private static uint currentID = 0; |
| 24 | + uint id = currentID++; |
16 | 25 |
|
17 | | - // Create an instance from its namespace |
18 | | - public static uint CreateInstance(string typeNamespace) |
| 26 | + try |
19 | 27 | { |
20 | | - uint id = currentID++; |
21 | | - |
22 | | - try |
23 | | - { |
24 | | - Type type = Assemblies.FindTypeInLoadedAssemblies(typeNamespace); |
25 | | - if (type == null) |
26 | | - { |
27 | | - Console.WriteLine($"[CreateInstance Error] Type '{typeNamespace}' not found in loaded assemblies."); |
28 | | - return 0; |
29 | | - } |
30 | | - |
31 | | - object instance = Activator.CreateInstance(type); |
32 | | - instanceMap[id] = instance; |
33 | | - return id; |
34 | | - } |
35 | | - catch (Exception ex) |
| 28 | + Type type = Assemblies.FindTypeInLoadedAssemblies(typeNamespace); |
| 29 | + if (type == null) |
36 | 30 | { |
37 | | - Console.WriteLine($"[CreateInstance Error] {ex.Message}"); |
| 31 | + Console.WriteLine($"[CreateInstance Error] Type '{typeNamespace}' not found in loaded assemblies."); |
38 | 32 | return 0; |
39 | 33 | } |
40 | | - } |
41 | 34 |
|
42 | | - // Delete an instance from its ID/Handle |
43 | | - // It's deconstructor will be called on the next GC cycle |
44 | | - public static void DeleteInstance(uint id) |
| 35 | + object instance = Activator.CreateInstance(type); |
| 36 | + instanceMap[id] = instance; |
| 37 | + return id; |
| 38 | + } |
| 39 | + catch (Exception ex) |
45 | 40 | { |
46 | | - instanceMap.Remove(id); |
| 41 | + Console.WriteLine($"[CreateInstance Error] {ex.Message}"); |
| 42 | + return 0; |
47 | 43 | } |
| 44 | + } |
48 | 45 |
|
49 | | - // Run an instance's method from its ID/Handle and the method name |
50 | | - public static void RunInstanceMethod(uint id, string methodCall) |
51 | | - { |
52 | | - // Get the instance |
53 | | - if (!instanceMap.TryGetValue(id, out object instance)) |
54 | | - return; |
| 46 | + /// <summary> |
| 47 | + /// Delete an instance from its ID/Handle. |
| 48 | + /// </summary> |
| 49 | + /// <param name="id">The ID/Handle.</param> |
| 50 | + public static void DeleteInstance(uint id) => instanceMap.Remove(id); |
55 | 51 |
|
56 | | - // Parse the method call into method name and arguments |
57 | | - Type type = instance.GetType(); |
58 | | - string methodName = ParseMethodName(methodCall, out string[] argStrings); |
| 52 | + /// <summary> |
| 53 | + /// Run an instance's method from its ID/Handle and the method name |
| 54 | + /// </summary> |
| 55 | + /// <param name="id">The ID/Handle.</param> |
| 56 | + /// <param name="methodCall">The method name.</param> |
| 57 | + public static void RunInstanceMethod(uint id, string methodCall) |
| 58 | + { |
| 59 | + // Get the instance |
| 60 | + if (!instanceMap.TryGetValue(id, out object instance)) |
| 61 | + return; |
59 | 62 |
|
60 | | - if (methodName == null) |
61 | | - return; |
| 63 | + // Parse the method call into method name and arguments |
| 64 | + Type type = instance.GetType(); |
| 65 | + string methodName = ParseMethodName(methodCall, out string[] argStrings); |
62 | 66 |
|
63 | | - // Find the method matching the name and the number of arguments |
64 | | - var method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); |
| 67 | + if (methodName == null) |
| 68 | + return; |
65 | 69 |
|
66 | | - if (method == null) |
67 | | - return; |
| 70 | + // Find the method matching the name and the number of arguments |
| 71 | + var method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); |
68 | 72 |
|
69 | | - // Convert arguments to the correct types |
70 | | - object[] args = ConvertArguments(method, argStrings); |
71 | | - method.Invoke(instance, args); |
72 | | - } |
| 73 | + if (method == null) |
| 74 | + return; |
73 | 75 |
|
74 | | - private static string ParseMethodName(string methodCall, out string[] args) |
75 | | - { |
76 | | - int parenStart = methodCall.IndexOf('('); |
77 | | - int parenEnd = methodCall.LastIndexOf(')'); |
| 76 | + // Convert arguments to the correct types |
| 77 | + object[] args = ConvertArguments(method, argStrings); |
| 78 | + method.Invoke(instance, args); |
| 79 | + } |
78 | 80 |
|
79 | | - if (parenStart == -1 || parenEnd == -1 || parenEnd <= parenStart) |
80 | | - { |
81 | | - args = null; |
82 | | - return null; |
83 | | - } |
| 81 | + private static string ParseMethodName(string methodCall, out string[] args) |
| 82 | + { |
| 83 | + int parenStart = methodCall.IndexOf('('); |
| 84 | + int parenEnd = methodCall.LastIndexOf(')'); |
84 | 85 |
|
85 | | - string methodName = methodCall.Substring(0, parenStart).Trim(); |
86 | | - string argsStr = methodCall.Substring(parenStart + 1, parenEnd - parenStart - 1).Trim(); |
| 86 | + if (parenStart == -1 || parenEnd == -1 || parenEnd <= parenStart) |
| 87 | + { |
| 88 | + args = null; |
| 89 | + return null; |
| 90 | + } |
87 | 91 |
|
88 | | - args = argsStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) |
89 | | - .Select(arg => arg.Trim()) |
90 | | - .ToArray(); |
| 92 | + string methodName = methodCall.Substring(0, parenStart).Trim(); |
| 93 | + string argsStr = methodCall.Substring(parenStart + 1, parenEnd - parenStart - 1).Trim(); |
91 | 94 |
|
92 | | - return methodName; |
93 | | - } |
| 95 | + args = argsStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) |
| 96 | + .Select(arg => arg.Trim()) |
| 97 | + .ToArray(); |
94 | 98 |
|
95 | | - private static object[] ConvertArguments(MethodInfo method, string[] argStrings) |
96 | | - { |
97 | | - ParameterInfo[] paramInfos = method.GetParameters(); |
98 | | - object[] finalArgs = new object[argStrings.Length]; |
| 99 | + return methodName; |
| 100 | + } |
99 | 101 |
|
100 | | - for (int i = 0; i < argStrings.Length; i++) |
101 | | - { |
102 | | - finalArgs[i] = Convert.ChangeType(argStrings[i], paramInfos[i].ParameterType); |
103 | | - } |
| 102 | + private static object[] ConvertArguments(MethodInfo method, string[] argStrings) |
| 103 | + { |
| 104 | + ParameterInfo[] paramInfos = method.GetParameters(); |
| 105 | + object[] finalArgs = new object[argStrings.Length]; |
104 | 106 |
|
105 | | - return finalArgs; |
| 107 | + for (int i = 0; i < argStrings.Length; i++) |
| 108 | + { |
| 109 | + finalArgs[i] = Convert.ChangeType(argStrings[i], paramInfos[i].ParameterType); |
106 | 110 | } |
| 111 | + |
| 112 | + return finalArgs; |
107 | 113 | } |
108 | 114 | } |
0 commit comments