ScriptStack 1.0.5
Loading...
Searching...
No Matches
Manager.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq.Expressions;
5using System.Reflection;
6using System.Text;
7
12
13namespace ScriptStack
14{
15
20 public class Manager
21 {
22
23 #region Private Variables
24
25 private string name;
28 private Dictionary<string, Routine> routines;
29 private Dictionary<object, Interpreter> locks;
30 private bool debug;
31 private bool optimize;
32
33 // Plugins loaded with isolated ALCs (keep references to prevent premature unload)
34 private List<Plugin> loadedPlugins = new List<Plugin>();
35
36 #endregion
37
38 #region Internal Properties
39
40 internal Dictionary<object, Interpreter> Locks
41 {
42 get { return locks; }
43 }
44
45 #endregion
46
47 #region Public Methods
48
52 public Manager()
53 {
54
55 scanner = new ScannerPrototype();
56
58
59 routines = new Dictionary<string, Routine>();
60
61 locks = new Dictionary<object, Interpreter>();
62
63 debug = false;
64
65 optimize = true;
66
67 loadedPlugins = new List<Plugin>();
68
69 }
70
71 public Func<List<string>, Lexer> LexerFactory { get; set; } = lines => new Lexer(lines);
72
73 public void LoadComponents(string relativeDirectoryPath)
74 {
75
76 string path = relativeDirectoryPath; // System.AppDomain.CurrentDomain.BaseDirectory;
77
78 if (!Directory.Exists(path))
79 return;
80
81 var subdirs = Directory.GetDirectories(path);
82 if (subdirs.Length > 0)
83 {
84 var shared = new[] { Assembly.GetExecutingAssembly().GetName().Name! };
85 var loaded = ScriptStack.Plugins.PluginLoader.LoadPlugins(path, this, shared);
86 this.loadedPlugins = loaded;
87 return;
88 }
89
90
91 foreach (string dll in System.IO.Directory.GetFiles(path, "*.dll"))
92 {
93
94 if (dll == path + "ScriptStack.dll")
95 continue;
96
97 Assembly assembly = null;
98
99 try
100 {
101 assembly = Assembly.LoadFile(dll);
102 }
103 catch (Exception e) {
104 Console.WriteLine($"[LoadComponents] Fehler beim Laden '{dll}': {e.Message}");
105
106 if (e is TargetInvocationException tie && tie.InnerException != null)
107 Console.WriteLine("INNER: " + tie.InnerException);
108
109 continue;
110 }
111
112 Type[] arrayTypes = assembly.GetExportedTypes();
113
114 foreach (Type type in arrayTypes)
115 {
116
117 if (!typeof(Model).IsAssignableFrom(type))
118 continue;
119
120 ConstructorInfo constructorInfo = null;
121 try
122 {
123 constructorInfo = type.GetConstructor(new Type[0]);
124 }
125 catch (Exception e) { continue; }
126
127 object objectHostModule = constructorInfo.Invoke(new object[0]);
128 Model hostModule = (Model)objectHostModule;
129
130 Register(hostModule);
131
132 }
133
134 }
135
136 }
137
138 public void LoadComponent(string relativeDirectoryPath)
139 {
140
141 Assembly assembly = null;
142 try
143 {
144 assembly = Assembly.LoadFile(relativeDirectoryPath);
145 }
146 catch (Exception e) { }
147
148 Type[] arrayTypes = assembly.GetExportedTypes();
149
150 foreach (Type type in arrayTypes)
151 {
152
153 if (!typeof(Model).IsAssignableFrom(type))
154 continue;
155
156 ConstructorInfo constructorInfo = null;
157 try
158 {
159 constructorInfo = type.GetConstructor(new Type[0]);
160 }
161 catch (Exception e) { continue; }
162
163 object objectHostModule = constructorInfo.Invoke(new object[0]);
164 Model hostModule = (Model)objectHostModule;
165
166 Register(hostModule);
167
168 }
169
170 }
171
173 {
174 get { return name; }
175 set {
176 name = value;
177 }
178 }
179
180 public bool IsRegistered(string routine)
181 {
182 return routines.ContainsKey(routine);
183 }
184
185 public void Register(Model model)
186 {
187
188 foreach (Routine routine in model.Routines)
189 Register(routine, model);
190
191 }
192
193 public void UnRegister(Model model)
194 {
195
196 foreach (Routine routine in model.Routines)
197 UnRegister(routine.Name);
198
199 }
200
201 public void Register(Routine routine, Host host)
202 {
203
204 string name = routine.Name;
205
206 if (routines.ContainsKey(name))
207 throw new ScriptStackException("Die Routine '" + name + "' ist bereits registriert.");
208
209 routine.Handler = host;
210
211 routines[name] = routine;
212
213 }
214
215 public void UnRegister(string routine)
216 {
217
218 if (!routines.ContainsKey(routine))
219 throw new ScriptStackException("Die Routine '" + routine + "' wurde nicht gefunden.");
220
221 routines.Remove(routine);
222
223 }
224
229 public void Register(Routine routine)
230 {
231 Register(routine, null);
232 }
233
234 public void ClearActiveLocks()
235 {
236 locks.Clear();
237 }
238
243 public void UnloadPlugins()
244 {
245 if (loadedPlugins == null || loadedPlugins.Count == 0)
246 return;
247
248 // Deregister routines
249 foreach (var plugin in loadedPlugins)
250 {
251 try
252 {
253 if (plugin?.Instance is Model model)
254 {
255 foreach (var r in model.Routines)
256 {
257 if (r != null && routines.ContainsKey(r.Name))
258 routines.Remove(r.Name);
259 }
260 }
261 }
262 catch (Exception ex)
263 {
264 Console.WriteLine($"[UnloadPlugins] Fehler beim Deregistrieren: {ex.Message}");
265 }
266 }
267
268 // Unload contexts
269 foreach (var plugin in loadedPlugins)
270 {
271 try
272 {
273 plugin.LoadContext?.Unload();
274 }
275 catch (Exception ex)
276 {
277 Console.WriteLine($"[UnloadPlugins] Fehler beim Unload: {ex.Message}");
278 }
279 }
280
281 loadedPlugins.Clear();
282
283 GC.Collect();
284 GC.WaitForPendingFinalizers();
285 GC.Collect();
286
287 }
288
289 #endregion
290
291 #region Public Properties
292
297 {
298 get { return scanner; }
299 set { scanner = value; }
300 }
301
303 {
304 get { return sharedMemory; }
305 }
306
307 public ReadOnlyDictionary<String, Routine> Routines {
308 get
309 {
310 return new ReadOnlyDictionary<string, Routine>(routines);
311 }
312 }
313
314 public bool Debug
315 {
316 get { return debug; }
317 set { debug = value; }
318 }
319
320 public bool Optimize
321 {
322 get { return optimize; }
323 set { optimize = value; }
324 }
325
326 public ReadOnlyDictionary<object, Interpreter> ActiveLocks
327 {
328 get { return new ReadOnlyDictionary<object,Interpreter>(locks); }
329 }
330
331 #endregion
332
333 }
334
335}
336
The lexical analyzer (Lexer) breaks code (written in sentences) into a series of known Token and pass...
Definition Lexer.cs:21
void LoadComponent(string relativeDirectoryPath)
Definition Manager.cs:138
void ClearActiveLocks()
Definition Manager.cs:234
Manager()
A Manager object is responsible for memory management, type evaluation and loading of plugins.
Definition Manager.cs:52
Memory sharedMemory
Definition Manager.cs:27
Func< List< string >, Lexer > LexerFactory
Definition Manager.cs:71
List< Plugin > loadedPlugins
Definition Manager.cs:34
void Register(Model model)
Definition Manager.cs:185
ReadOnlyDictionary< object, Interpreter > ActiveLocks
Definition Manager.cs:327
void UnloadPlugins()
Unload all plugins that were loaded via LoadComponents (subdirectory mode). This will deregister thei...
Definition Manager.cs:243
bool IsRegistered(string routine)
Definition Manager.cs:180
Scanner Scanner
A Scanner reference.
Definition Manager.cs:297
void UnRegister(string routine)
Definition Manager.cs:215
Dictionary< string, Routine > routines
Definition Manager.cs:28
void LoadComponents(string relativeDirectoryPath)
Definition Manager.cs:73
Dictionary< object, Interpreter > locks
Definition Manager.cs:29
void Register(Routine routine)
Register a new Routine.
Definition Manager.cs:229
void UnRegister(Model model)
Definition Manager.cs:193
ReadOnlyDictionary< String, Routine > Routines
Definition Manager.cs:307
void Register(Routine routine, Host host)
Definition Manager.cs:201
static List< Plugin > LoadPlugins(string pluginsRoot, ScriptStack.Manager manager, string[]? sharedAssemblyNames=null)
static Memory AllocateSharedMemory()
Definition Memory.cs:55
A Routine is an abstract representation of a method.
Definition Routine.cs:70
The main interface to create a Host. A Host can implement Routine's to extend its functionality.
Definition Host.cs:80