HamBook – Blame information for rev 58

Subversion Repositories:
Rev:
Rev Author Line No. Line
54 office 1 using System;
1 office 2 using System.Collections.Concurrent;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Reflection;
6 using System.Runtime.CompilerServices;
7 using System.Threading;
8 using System.Threading.Tasks;
54 office 9 using HamBook.Properties;
10 using RJCP.IO.Ports;
11 using Serilog;
1 office 12  
13 namespace HamBook.Radios
14 {
15 public class CatAssemblies : IDisposable
16 {
54 office 17 private readonly ConcurrentDictionary<string, Cat> _catCommands;
18 private readonly string _radio;
19 private readonly SemaphoreSlim _semaphoreSlim;
20 private readonly SerialPortStream _serialPort;
1 office 21  
22 private int _count;
23  
24 private CatAssemblies()
25 {
26 _catCommands = new ConcurrentDictionary<string, Cat>();
26 office 27 _semaphoreSlim = new SemaphoreSlim(1, 1);
1 office 28 }
29  
9 office 30 public CatAssemblies(SerialPortStream serialPort, string radio) : this()
1 office 31 {
32 _serialPort = serialPort;
33 _radio = radio;
34  
35 Load(_radio);
36 }
54 office 37  
38 public int Count => _count;
39  
1 office 40 public void Dispose()
41 {
42 Unload();
43 }
44  
45 private void Load(string radio)
46 {
47 Interlocked.Exchange(ref _count, 0);
48  
49 foreach (var type in Assembly.GetExecutingAssembly()
54 office 50 .GetTypes()
51 .Where(type => type.IsSubclassOf(typeof(Cat)))
52 .Where(type =>
53 type.GetCustomAttribute<RadioAttribute>() != null &&
54 type.GetCustomAttribute<RadioAttribute>().Radio == radio))
1 office 55 try
56 {
57 var catCommand = (Cat)type
58 office 58 .GetConstructor(new[] { typeof(SerialPortStream) })?.Invoke(new object[] { _serialPort });
1 office 59  
54 office 60 if (catCommand == null) throw new ArgumentException(Resources.Could_not_create_assembly);
1 office 61  
62 if (!_catCommands.TryAdd(catCommand.Name, catCommand))
63 {
64 Log.Warning(Resources.Unable_to_register_assembly, catCommand.Name);
65  
66 catCommand.Dispose();
67  
68 continue;
69 }
70  
71 //BindEventHandlers(command);
72 Interlocked.Increment(ref _count);
73 }
74 catch (Exception exception)
75 {
76 Log.Error(exception, Resources.Could_not_instantiate_assembly, type);
77 }
78  
79 Log.Information(Resources.Registering_commands, Count);
80 }
81  
82 private void Unload()
83 {
84 // Dispose all command assemblies.
85 var list = new List<Cat>(_catCommands.Values);
86  
87 for (var i = 0; i < list.Count; ++i)
88 try
89 {
90 //UnbindEventHandlers(list[i]);
91 if (list[i] != null)
92 {
93 Log.Debug(Resources.Disposing_assembly, list[i].GetType().Name);
94  
95 list[i]
96 .Dispose();
97  
98 list[i] = null;
99 }
100 }
101 catch (NullReferenceException)
102 {
103 // Already removed.
104 }
105 catch (ObjectDisposedException)
106 {
107 list[i] = null;
108 }
109 catch (Exception exception)
110 {
111 Log.Error(exception, Resources.Error_encountered_while_disposing_object);
112 }
113  
114 _catCommands.Clear();
115 }
116  
58 office 117 public bool CatParse<T>(string command, object[] param, out T output)
1 office 118 {
58 office 119 if (!_catCommands.TryGetValue(command, out var catCommand))
120 throw new CatCommandException(Resources.CAT_command_not_found, command);
121  
122 var methodInfo = catCommand.GetType().GetMethod("Parse");
123 if (methodInfo == null)
3 office 124 {
26 office 125 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "Parse");
58 office 126  
3 office 127 }
128  
58 office 129 output = default;
130 try
131 {
132 output = (T)methodInfo.Invoke(catCommand, param);
133 }
134 catch
135 {
136 return false;
137 }
138  
139 return true;
26 office 140 }
141  
142 public T CatGetDefault<T>(string command, object[] param)
143 {
144 _semaphoreSlim.Wait();
145  
1 office 146 try
147 {
54 office 148 if (!_serialPort.IsOpen) _serialPort.Open();
26 office 149  
58 office 150 if (_catCommands.TryGetValue(command, out var catCommand))
26 office 151 {
58 office 152 var methodInfo = catCommand.GetType().GetMethod("GetDefault");
153  
154 if (methodInfo != null)
1 office 155 {
58 office 156 return (T)methodInfo.Invoke(catCommand, param);
1 office 157 }
158 }
159 }
160 finally
161 {
58 office 162 if (_serialPort.IsOpen)
163 {
164 _serialPort.Flush();
165 _serialPort.Close();
166 }
167  
26 office 168 _semaphoreSlim.Release();
1 office 169 }
9 office 170  
171 return default;
1 office 172 }
173  
58 office 174 public void CatSet(string command, object[] param)
9 office 175 {
26 office 176 _semaphoreSlim.Wait();
177 try
9 office 178 {
54 office 179 if (!_serialPort.IsOpen) _serialPort.Open();
11 office 180  
58 office 181 if (!_catCommands.TryGetValue(command, out var catCommand))
182 throw new CatCommandException(Resources.CAT_command_not_found, command);
9 office 183  
58 office 184 var methodInfo = catCommand.GetType().GetMethod("Set") ??
185 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "Set");
9 office 186  
58 office 187 methodInfo.Invoke(catCommand, param);
1 office 188 }
189 finally
190 {
58 office 191 if (_serialPort.IsOpen)
192 {
193 _serialPort.Flush();
194 _serialPort.Close();
195 }
196  
26 office 197 _semaphoreSlim.Release();
1 office 198 }
199 }
200  
54 office 201 public async Task<TU> CatSetAsync<T, TU>(string command, object[] param, CancellationToken cancellationToken)
3 office 202 {
26 office 203 await _semaphoreSlim.WaitAsync(cancellationToken);
3 office 204  
205 try
206 {
54 office 207 if (!_serialPort.IsOpen) _serialPort.Open();
26 office 208  
58 office 209 if (!_catCommands.TryGetValue(command, out var catCommand))
210 throw new CatCommandException(Resources.CAT_command_not_found, command);
9 office 211  
58 office 212 var methodInfo = catCommand.GetType().GetMethod("SetAsync") ??
213 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "SetAsync");
11 office 214  
58 office 215 if (methodInfo.GetCustomAttribute<AsyncStateMachineAttribute>() == null)
216 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "SetAsync");
54 office 217  
58 office 218 var parameters = new List<object>();
219 parameters.AddRange(param);
220 parameters.Add(cancellationToken);
26 office 221  
58 office 222 var result = await (Task<TU>)methodInfo.Invoke(catCommand, parameters.ToArray());
223  
224 return result;
3 office 225 }
226 finally
227 {
58 office 228 if (_serialPort.IsOpen)
229 {
230 await _serialPort.FlushAsync(cancellationToken);
231 _serialPort.Close();
232 }
233  
26 office 234 _semaphoreSlim.Release();
3 office 235 }
9 office 236 }
3 office 237  
9 office 238 public void CatWrite<T>(string command, object[] param)
239 {
26 office 240 _semaphoreSlim.Wait();
9 office 241  
242 try
243 {
54 office 244 if (!_serialPort.IsOpen) _serialPort.Open();
26 office 245  
58 office 246 if (!_catCommands.TryGetValue(command, out var catCommand))
247 throw new CatCommandException(Resources.CAT_command_not_found, command);
11 office 248  
58 office 249 var methodInfo = catCommand.GetType().GetMethod("Write") ??
250 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "Write");
26 office 251  
58 office 252 methodInfo.Invoke(catCommand, param);
9 office 253 }
254 finally
255 {
58 office 256 if (_serialPort.IsOpen)
257 {
258 _serialPort.Flush();
259 _serialPort.Close();
260 }
261  
26 office 262 _semaphoreSlim.Release();
9 office 263 }
3 office 264 }
265  
9 office 266 public async Task CatWriteAsync<T>(string command, object[] param, CancellationToken cancellationToken)
3 office 267 {
26 office 268 await _semaphoreSlim.WaitAsync(cancellationToken);
3 office 269  
270 try
271 {
54 office 272 if (!_serialPort.IsOpen) _serialPort.Open();
26 office 273  
58 office 274 if (!_catCommands.TryGetValue(command, out var catCommand))
275 throw new CatCommandException(Resources.CAT_command_not_found, command);
9 office 276  
58 office 277 var methodInfo = catCommand.GetType().GetMethod("WriteAsync") ??
278 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "WriteAsync");
11 office 279  
58 office 280 if (methodInfo.GetCustomAttribute<AsyncStateMachineAttribute>() == null)
281 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "WriteAsync");
26 office 282  
58 office 283 var parameters = new List<object>();
284 parameters.AddRange(param);
285 parameters.Add(cancellationToken);
11 office 286  
58 office 287 await (Task)methodInfo.Invoke(catCommand, parameters.ToArray());
288 }
289 finally
290 {
291 if (_serialPort.IsOpen)
26 office 292 {
58 office 293 await _serialPort.FlushAsync(cancellationToken);
294 _serialPort.Close();
26 office 295 }
58 office 296  
297 _semaphoreSlim.Release();
3 office 298 }
58 office 299 }
300  
301 public async Task CatWriteAsyncManual<T>(string command, object[] param, CancellationToken cancellationToken)
302 {
303 await _semaphoreSlim.WaitAsync(cancellationToken);
304  
305 try
306 {
307 if (!_serialPort.IsOpen) _serialPort.Open();
308  
309 if (!_catCommands.TryGetValue(command, out var catCommand))
310 throw new CatCommandException(Resources.CAT_command_not_found, command);
311  
312 var methodInfo = catCommand.GetType().GetMethod("WriteAsync") ??
313 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "WriteAsync");
314  
315 if (methodInfo.GetCustomAttribute<AsyncStateMachineAttribute>() == null)
316 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "WriteAsync");
317  
318 var parameters = new List<object>();
319 parameters.AddRange(param);
320 parameters.Add(cancellationToken);
321  
322 await (Task)methodInfo.Invoke(catCommand, parameters.ToArray());
323 }
3 office 324 finally
325 {
58 office 326 if (_serialPort.IsOpen)
327 {
328 await _serialPort.FlushAsync(cancellationToken);
329 }
330  
26 office 331 _semaphoreSlim.Release();
3 office 332 }
333 }
334  
38 office 335 public async Task CatWriteAsync(string command, object[] param, CancellationToken cancellationToken)
336 {
337 await _semaphoreSlim.WaitAsync(cancellationToken);
338  
339 try
340 {
54 office 341 if (!_serialPort.IsOpen) _serialPort.Open();
38 office 342  
58 office 343 if (!_catCommands.TryGetValue(command, out var catCommand))
344 throw new CatCommandException(Resources.CAT_command_not_found, command);
38 office 345  
58 office 346 var methodInfo = catCommand.GetType().GetMethod("WriteAsync") ??
347 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "WriteAsync");
38 office 348  
58 office 349 if (methodInfo.GetCustomAttribute<AsyncStateMachineAttribute>() == null)
350 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "WriteAsync");
38 office 351  
58 office 352 var parameters = new List<object>();
353 parameters.AddRange(param);
354 parameters.Add(cancellationToken);
38 office 355  
58 office 356 await (Task)methodInfo.Invoke(catCommand, parameters.ToArray());
38 office 357 }
358 finally
359 {
58 office 360 if (_serialPort.IsOpen)
361 {
362 await _serialPort.FlushAsync(cancellationToken);
363 _serialPort.Close();
364 }
365  
38 office 366 _semaphoreSlim.Release();
367 }
368 }
369  
1 office 370 public T CatRead<T>(string command, object[] param)
371 {
26 office 372 _semaphoreSlim.Wait();
3 office 373  
1 office 374 try
375 {
54 office 376 if (!_serialPort.IsOpen) _serialPort.Open();
26 office 377  
58 office 378 if (!_catCommands.TryGetValue(command, out var catCommand))
379 throw new CatCommandException(Resources.CAT_command_not_found, command);
26 office 380  
58 office 381 var methodInfo = catCommand.GetType().GetMethod("Read");
382 if (methodInfo != null) return (T)methodInfo.Invoke(catCommand, param);
11 office 383  
58 office 384 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "Read");
1 office 385 }
386 finally
387 {
58 office 388 if (_serialPort.IsOpen)
389 {
390 _serialPort.Flush();
391 _serialPort.Close();
392 }
393  
26 office 394 _semaphoreSlim.Release();
1 office 395 }
396 }
397  
9 office 398 public async Task<T> CatReadAsync<T>(string command, object[] param, CancellationToken cancellationToken)
1 office 399 {
26 office 400 await _semaphoreSlim.WaitAsync(cancellationToken);
3 office 401  
1 office 402 try
403 {
54 office 404 if (!_serialPort.IsOpen) _serialPort.Open();
26 office 405  
58 office 406 if (_catCommands.TryGetValue(command, out var catCommand))
26 office 407 {
58 office 408 var methodInfo = catCommand.GetType().GetMethod("ReadAsync") ??
409 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "ReadAsync");
9 office 410  
58 office 411 if (methodInfo.GetCustomAttribute<AsyncStateMachineAttribute>() == null)
412 throw new CatCommandException(Resources.CAT_command_method_not_found, command, "ReadAsync");
27 office 413  
58 office 414 var parameters = new List<object>();
415 parameters.AddRange(param);
416 parameters.Add(cancellationToken);
26 office 417  
58 office 418 var result = await (Task<T>)methodInfo.Invoke(catCommand, parameters.ToArray());
11 office 419  
58 office 420 return result;
421  
1 office 422 }
58 office 423  
424 throw new CatCommandException(Resources.CAT_command_not_found, command);
1 office 425 }
426 finally
427 {
58 office 428 if (_serialPort.IsOpen)
429 {
430 await _serialPort.FlushAsync(cancellationToken);
431 _serialPort.Close();
432 }
433  
26 office 434 _semaphoreSlim.Release();
1 office 435 }
436 }
437 }
54 office 438 }