ObjectInstanceCreator.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. using Edge.Core.Parser.BinaryParser;
  2. using Edge.Core.Processor.Communicator;
  3. using Edge.Core.Processor.Dispatcher.Attributes;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Text.Json.Serialization;
  10. using System.Text.Json;
  11. using System.Threading.Tasks;
  12. using Microsoft.Extensions.Logging;
  13. using Microsoft.Extensions.Logging.Abstractions;
  14. namespace Edge.Core.Processor.Dispatcher
  15. {
  16. public static class ObjectInstanceCreator
  17. {
  18. public static ILogger mainLogger = Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance;
  19. static JsonSerializerOptions jsonSerializerOptions;
  20. static string plugInFolder = "plugin";
  21. private static IEnumerable<Assembly> LoadPlugInAssemblies()
  22. {
  23. //var assemblyFileInfos = new DirectoryInfo(Directory.GetCurrentDirectory()).GetFiles()
  24. // .Where(f => f.Extension != null
  25. // && (f.Extension.ToLower() == ".dll" || f.Extension.ToLower() == ".exe")
  26. // && !f.Name.Contains("Microsoft"));
  27. //if (mainLogger.IsEnabled(LogLevel.Trace))
  28. //{
  29. // mainLogger.LogTrace("LoadPlugInAssemblies, root folder(" + Directory.GetCurrentDirectory() + ") loaded assembly files: " +
  30. // assemblyFileInfos.Select(fi => fi.Name + ", Length: " + fi.Length +
  31. // ", CreationTimeUtc: " + fi.CreationTimeUtc +
  32. // ", LastAccessTimeUtc: " + fi.LastAccessTimeUtc + ", LastWriteTimeUtc: " + fi.LastWriteTimeUtc)
  33. // .Aggregate(Environment.NewLine, (acc, n) => acc + n + Environment.NewLine));
  34. //}
  35. if (Directory.Exists(Directory.GetCurrentDirectory() + "\\" + plugInFolder))
  36. {
  37. var plugInFolderAssemblyFileInfos = new DirectoryInfo(Directory.GetCurrentDirectory() + "\\" + plugInFolder).GetFiles()
  38. .Where(f => f.Extension != null
  39. && (f.Extension.ToLower() == ".dll" || f.Extension.ToLower() == ".exe")
  40. && !f.Name.Contains("Microsoft"));
  41. if (mainLogger.IsEnabled(LogLevel.Trace))
  42. {
  43. mainLogger.LogTrace("LoadPlugInAssemblies, plugIn folder(path: " + plugInFolder + ") contains assembly files: " +
  44. plugInFolderAssemblyFileInfos.Select(fi => fi.Name + ", Length: " + fi.Length +
  45. ", CreationTimeUtc: " + fi.CreationTimeUtc +
  46. ", LastAccessTimeUtc: " + fi.LastAccessTimeUtc + ", LastWriteTimeUtc: " + fi.LastWriteTimeUtc)
  47. .Aggregate(Environment.NewLine, (acc, n) => acc + n + Environment.NewLine));
  48. }
  49. var rootFolderAssemblyFileInfos = new DirectoryInfo(Directory.GetCurrentDirectory()).GetFiles()
  50. .Where(f => f.Extension != null
  51. && (f.Extension.ToLower() == ".dll" || f.Extension.ToLower() == ".exe")
  52. && !f.Name.Contains("Microsoft"));
  53. var plugInFolderDuplicatedFileInfos =
  54. plugInFolderAssemblyFileInfos.Join(rootFolderAssemblyFileInfos, fi => fi.Name, fi => fi.Name, (outer, inner) => outer);
  55. if (mainLogger.IsEnabled(LogLevel.Information))
  56. {
  57. if (plugInFolderDuplicatedFileInfos.Any())
  58. mainLogger.LogInformation("LoadPlugInAssemblies, duplicated PlugIn assembly files found in plugIn folder(path: " + plugInFolder + "): " +
  59. plugInFolderDuplicatedFileInfos.Select(fi => fi.Name + ", Length: " + fi.Length +
  60. ", CreationTimeUtc: " + fi.CreationTimeUtc +
  61. ", LastAccessTimeUtc: " + fi.LastAccessTimeUtc +
  62. ", LastWriteTimeUtc: " + fi.LastWriteTimeUtc)
  63. .Aggregate(Environment.NewLine, (acc, n) => acc + n + Environment.NewLine) +
  64. Environment.NewLine + "Will keep the one in rootFolder which should already loaded into CurrentDomain");
  65. }
  66. return plugInFolderAssemblyFileInfos.Where(fi => !plugInFolderDuplicatedFileInfos.Select(dFi => dFi.Name).Contains(fi.Name))
  67. .Select(fi =>
  68. {
  69. try
  70. {
  71. var ass = Assembly.LoadFrom(fi.FullName);
  72. if (mainLogger.IsEnabled(LogLevel.Trace))
  73. {
  74. mainLogger.LogTrace("LoadPlugInAssemblies, Loaded assembly by Assembly.LoadFrom: " + fi.FullName);
  75. }
  76. return ass;
  77. }
  78. catch (Exception eeee)
  79. {
  80. mainLogger.LogInformation("LoadPlugInAssemblies, Failed to Loaded assembly by Assembly.LoadFrom: " + fi.FullName +
  81. Environment.NewLine + eeee + Environment.NewLine + "Will skip this assembly...");
  82. return null;
  83. }
  84. });
  85. }
  86. else
  87. {
  88. mainLogger.LogInformation("LoadPlugInAssemblies, failed due to no plugIn folder found");
  89. return null;
  90. };
  91. }
  92. /// <summary>
  93. ///
  94. /// </summary>
  95. /// <param name="assemblyFullName">Gets the full name of the assembly, also known as the display name.</param>
  96. /// <returns></returns>
  97. internal static Assembly DefaultSearchLocalAssemblyFileAssemblyResolver(string assemblyFullName, Assembly? requestingAssembly)
  98. {
  99. try
  100. {
  101. var targetAssembly = CurrentDomainAssemblies.Where(ass => ass.FullName == assemblyFullName).FirstOrDefault();
  102. if (targetAssembly == null)
  103. {
  104. if (mainLogger.IsEnabled(LogLevel.Information))
  105. mainLogger.LogInformation("AssemblyResolver, could not resolving: " + assemblyFullName +
  106. " from CurrentDomain assemblies" +
  107. ", the requestingAssembly is: " + (requestingAssembly?.FullName ?? "") +
  108. ", Try loading PlugIn...");
  109. var plugInAssemblies = LoadPlugInAssemblies();
  110. if (plugInAssemblies != null)
  111. foreach (var piAss in plugInAssemblies)
  112. {
  113. if (piAss != null && piAss.FullName == assemblyFullName) { targetAssembly = piAss; break; }
  114. }
  115. }
  116. if (mainLogger.IsEnabled(LogLevel.Information))
  117. if (targetAssembly != null)
  118. mainLogger.LogInformation("AssemblyResolver, resolved: " + assemblyFullName +
  119. " as assembly: " + (targetAssembly?.FullName ?? "") +
  120. ", the requestingAssembly is: " + (requestingAssembly?.FullName ?? ""));
  121. else
  122. mainLogger.LogInformation("AssemblyResolver, failed for resolving: " + assemblyFullName +
  123. ", the requestingAssembly is: " + (requestingAssembly?.FullName ?? ""));
  124. return targetAssembly;
  125. }
  126. catch (Exception eeee)
  127. {
  128. mainLogger.LogInformation("AssemblyResolver, failed for resolving: " + assemblyFullName +
  129. " with exception: " + eeee);
  130. return null;
  131. }
  132. }
  133. /// <summary>
  134. ///
  135. /// </summary>
  136. /// <param name="typeFullName">Gets the fully qualified name of the type, including its namespace but not its assembly.</param>
  137. /// <returns></returns>
  138. internal static Type DefaultSearchLocalAssemblyFileTypeResolver(string typeFullName, Assembly? requestingAssembly)
  139. {
  140. var targetType = CurrentDomainAssemblies.Where(ass => !ass.FullName.Contains("Microsoft"))
  141. .SelectMany(a => { Type[] ts = new Type[] { }; try { ts = a.GetTypes(); } catch { } return ts; }).FirstOrDefault(t => t.FullName == typeFullName);
  142. if (targetType == null)
  143. {
  144. if (mainLogger.IsEnabled(LogLevel.Information))
  145. mainLogger.LogInformation("TypeResolver, could not resolving: " + typeFullName + " from CurrentDomain assemblies" +
  146. ", the requestingAssembly is: " + (requestingAssembly?.FullName ?? "") +
  147. ", Try loading plugIn from folder path: " + plugInFolder);
  148. var plugInAssemblies = LoadPlugInAssemblies();
  149. if (plugInAssemblies != null)
  150. foreach (var piAss in plugInAssemblies.Where(ass => ass != null))
  151. {
  152. try
  153. {
  154. targetType = piAss.GetTypes().FirstOrDefault(t => t.FullName == typeFullName);
  155. if (targetType == null) continue;
  156. else break;
  157. }
  158. catch (Exception eeee)
  159. { continue; }
  160. }
  161. }
  162. if (mainLogger.IsEnabled(LogLevel.Information))
  163. if (targetType != null)
  164. mainLogger.LogInformation("TypeResolver, resolved: " + typeFullName + " as type: " + (targetType?.FullName ?? "") +
  165. " in assembly: " + (targetType?.Assembly?.FullName ?? "") +
  166. ", the requestingAssembly is: " + (requestingAssembly?.FullName ?? ""));
  167. else
  168. mainLogger.LogInformation("TypeResolver, failed for resolving: " + typeFullName + ", the requestingAssembly is: " + (requestingAssembly?.FullName ?? ""));
  169. return targetType;
  170. }
  171. public static IEnumerable<Assembly> CurrentDomainAssemblies { get; private set; }
  172. static ObjectInstanceCreator()
  173. {
  174. var reloadAll_avoid_missing_typesSpecifiedWithoutAssemblyQualifiedName_fi =
  175. new DirectoryInfo(Directory.GetCurrentDirectory()).GetFiles()
  176. .Where(f => f.Extension != null
  177. && (f.Extension.ToLower() == ".dll" || f.Extension.ToLower() == ".exe")
  178. && !f.Name.Contains("Microsoft"));
  179. foreach (var fi in reloadAll_avoid_missing_typesSpecifiedWithoutAssemblyQualifiedName_fi)
  180. {
  181. try
  182. {
  183. //duplicated ass will be auto ignored.
  184. var ass = Assembly.LoadFrom(fi.FullName);
  185. }
  186. catch (Exception eeee)
  187. {
  188. }
  189. }
  190. CurrentDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
  191. AppDomain.CurrentDomain.TypeResolve += (s, args) =>
  192. {
  193. var type = ObjectInstanceCreator.DefaultSearchLocalAssemblyFileTypeResolver(args.Name, args.RequestingAssembly);
  194. return type?.Assembly;
  195. };
  196. AppDomain.CurrentDomain.AssemblyResolve += (s, args) =>
  197. {
  198. return DefaultSearchLocalAssemblyFileAssemblyResolver(args.Name, args.RequestingAssembly);
  199. };
  200. jsonSerializerOptions = new JsonSerializerOptions()
  201. {
  202. WriteIndented = true,
  203. PropertyNameCaseInsensitive = true,
  204. };
  205. jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
  206. }
  207. public static object Create(string fullTypeStr, Type[] genericTypeParameters, JsonElement[] ctorInputJsonParameters, object[] dependencies)
  208. {
  209. if (string.IsNullOrEmpty(fullTypeStr)) throw new ArgumentNullException(nameof(fullTypeStr));
  210. var type = Type.GetType(fullTypeStr);
  211. if (type == null) throw new InvalidOperationException("Could not get the type for fullTypeStr: " + fullTypeStr);
  212. if (type.IsGenericType)
  213. if (genericTypeParameters == null || !genericTypeParameters.Any())
  214. throw new InvalidOperationException("Must provide Generic type args for instantiate generic type: " + type.FullName);
  215. else
  216. type = type.MakeGenericType(genericTypeParameters);
  217. var potentialCtors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  218. if ((ctorInputJsonParameters?.Length ?? 0) == 0
  219. && (potentialCtors == null || !potentialCtors.Any() || potentialCtors.Any(pct => pct.GetParameters().Length == 0)))
  220. return Activator.CreateInstance(type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, null, null, null);
  221. if ((dependencies == null || !dependencies.Any()) && (potentialCtors == null || !potentialCtors.Any())) throw new InvalidOperationException("Can't find constructor with parameter count ==" + (ctorInputJsonParameters?.Length ?? 0) + " for type: " + fullTypeStr);
  222. List<object> ctrParameterInstances = new List<object>();
  223. foreach (var ctr in potentialCtors)
  224. {
  225. int injectedTimes = 0;
  226. int nextCtorParameterIndex = 0;
  227. for (int i = 0; i < ctr.GetParameters().Length; i++)
  228. {
  229. var ctrParaInfo = ctr.GetParameters()[i];
  230. try
  231. {
  232. var part = dependencies?.FirstOrDefault(ip =>
  233. {
  234. if (ip == null) return false;
  235. //if (ctrParaInfo.ParameterType.IsGenericType && ctrParaInfo.ParameterType.ge)
  236. // return IsAssignableToGenericType(ctrParaInfo.ParameterType, ip.GetType());
  237. var debug = ctrParaInfo.ParameterType;
  238. return debug.IsAssignableFrom(ip.GetType());
  239. });
  240. if (part != null)
  241. { ctrParameterInstances.Add(part); injectedTimes++; continue; }
  242. var ctrParameterInstance = System.Text.Json.JsonSerializer.Deserialize(
  243. ctorInputJsonParameters[nextCtorParameterIndex].GetRawText(),
  244. ctrParaInfo.ParameterType,
  245. jsonSerializerOptions);
  246. nextCtorParameterIndex++;
  247. ctrParameterInstances.Add(ctrParameterInstance);
  248. }
  249. catch (Exception exx)
  250. {
  251. /*any exception indicates the operating ctor is not the expecting one, should try next Ctor*/
  252. ctrParameterInstances.Clear();
  253. break;
  254. }
  255. }
  256. if (ctrParameterInstances.Any()
  257. && ctrParameterInstances.Count == (injectedTimes + ctorInputJsonParameters.Length))
  258. {
  259. try
  260. {
  261. var instance = Activator.CreateInstance(type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, ctrParameterInstances.ToArray(), null, null);
  262. return instance;
  263. }
  264. catch (Exception exx)
  265. {
  266. throw new InvalidOperationException("CreateInstance caught inner exception for type: " + type.FullName + Environment.NewLine + exx);
  267. }
  268. }
  269. else ctrParameterInstances.Clear();
  270. }
  271. throw new JsonConfigNotCompatibleWithAnyCtorDeclarationException(type, null, null, ctorInputJsonParameters);
  272. }
  273. /// <summary>
  274. /// looped all ctors and could not fit anyone with the deserialized types from ctorInputJsonParameters.
  275. /// </summary>
  276. public class JsonConfigNotCompatibleWithAnyCtorDeclarationException : Exception
  277. {
  278. public JsonConfigNotCompatibleWithAnyCtorDeclarationException(
  279. Type targetType, ConstructorInfo targetCtor, ParameterInfo targetParameter,
  280. JsonElement[] ctorInputJsonParameters)
  281. {
  282. this.TargetType = targetType;
  283. this.TargetCtor = targetCtor;
  284. this.TargetParameter = targetParameter;
  285. this.CtorInputJsonParameters = ctorInputJsonParameters;
  286. }
  287. public Type TargetType { get; private set; }
  288. public ConstructorInfo TargetCtor { get; private set; }
  289. public ParameterInfo TargetParameter { get; private set; }
  290. public JsonElement[] CtorInputJsonParameters { get; private set; }
  291. }
  292. //public static T Create<T>(JsonElement[] ctorParameters, Type[] genericTypeParameters, object[] dependencies) //where T : Type
  293. //{
  294. // return (T)Create(typeof(T).FullName, genericTypeParameters, ctorParameters, dependencies);
  295. //}
  296. //public static bool IsAssignableToGenericType(Type givenType, Type genericType)
  297. //{
  298. // var interfaceTypes = givenType.GetInterfaces();
  299. // foreach (var it in interfaceTypes)
  300. // {
  301. // if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
  302. // return true;
  303. // }
  304. // if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
  305. // return true;
  306. // Type baseType = givenType.BaseType;
  307. // if (baseType == null) return false;
  308. // return IsAssignableToGenericType(baseType, genericType);
  309. //}
  310. /// <summary>
  311. ///
  312. /// </summary>
  313. /// <typeparam name="T">must a concrete type, not interface or abstract</typeparam>
  314. /// <param name="ctorParametersJsonStr"></param>
  315. /// <param name="genericTypeParameters"></param>
  316. /// <param name="dependencies"></param>
  317. /// <returns></returns>
  318. public static T Create<T>(string ctorParametersJsonStr, Type[] genericTypeParameters, object[] dependencies) //where T : Type
  319. {
  320. var inputParameter = JsonDocument.Parse(ctorParametersJsonStr).RootElement;
  321. JsonElement[] inputParameters = null;
  322. if (inputParameter.ValueKind == JsonValueKind.Array)
  323. inputParameters = inputParameter.EnumerateArray().ToArray();
  324. else if (inputParameter.ValueKind == JsonValueKind.Object)
  325. inputParameters = new JsonElement[] { inputParameter };
  326. else if (inputParameter.ValueKind == JsonValueKind.Undefined)
  327. { }
  328. else
  329. inputParameters = new JsonElement[] { inputParameter };
  330. return (T)Create(typeof(T).FullName, genericTypeParameters, inputParameters, dependencies);
  331. }
  332. public static object Create(string fullTypeStr, string ctorParametersJsonStr, Type[] genericTypeParameters, object[] dependencies) //where T : Type
  333. {
  334. if (string.IsNullOrEmpty(ctorParametersJsonStr)) ctorParametersJsonStr = "[]";
  335. var inputParameter = JsonDocument.Parse(ctorParametersJsonStr).RootElement;
  336. JsonElement[] inputParameters = null;
  337. if (inputParameter.ValueKind == JsonValueKind.Array)
  338. inputParameters = inputParameter.EnumerateArray().ToArray();
  339. else if (inputParameter.ValueKind == JsonValueKind.Object)
  340. inputParameters = new JsonElement[] { inputParameter };
  341. else if (inputParameter.ValueKind == JsonValueKind.Undefined)
  342. { }
  343. else
  344. inputParameters = new JsonElement[] { inputParameter };
  345. return Create(fullTypeStr, genericTypeParameters, inputParameters, dependencies);
  346. }
  347. public static T CreateProcessor<T>(ProcessorMetaConfig metaConfig, object[] dependencies) where T : IProcessor
  348. {
  349. if (metaConfig == null) throw new ArgumentNullException(nameof(metaConfig));
  350. T processorInstance = default(T);
  351. if (metaConfig.Parts.Any(p => p.Type == ProcessorMetaPartsTypeEnum.App))
  352. {
  353. processorInstance = (T)ObjectInstanceCreator.Create(
  354. metaConfig.Parts.First(p => p.Type == ProcessorMetaPartsTypeEnum.App).FullTypeString,
  355. null,
  356. JsonDocument.Parse(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.App)
  357. .ParametersJsonArrayStr ?? "[]").RootElement.EnumerateArray().ToArray(),
  358. dependencies);
  359. if (processorInstance == null)
  360. throw new ArgumentException("Failed for resolving AppProcessor from Type: " + metaConfig.Parts.First(p => p.Type == ProcessorMetaPartsTypeEnum.App).FullTypeString);
  361. }
  362. else if (metaConfig.Parts.Any(p => p.Type == ProcessorMetaPartsTypeEnum.DeviceHandler))
  363. {
  364. var deviceHandlerInstance = ObjectInstanceCreator.Create(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.DeviceHandler).FullTypeString,
  365. null,
  366. JsonDocument.Parse(metaConfig.Parts.First(p => p.Type == ProcessorMetaPartsTypeEnum.DeviceHandler)
  367. .ParametersJsonArrayStr ?? "[]").RootElement.EnumerateArray().ToArray(),
  368. dependencies);
  369. if (deviceHandlerInstance == null)
  370. throw new ArgumentException("Failed for resolving deviceHandlerInstance from Type: " + metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.DeviceHandler).FullTypeString);
  371. #region Create Parts of RawMessage Type
  372. Type rawMessageType = null;
  373. if (!string.IsNullOrEmpty(metaConfig?.Parts?.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.RawMessageTypeStr)?.FullTypeString))
  374. {
  375. rawMessageType = Type.GetType(metaConfig?.Parts?.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.RawMessageTypeStr)?.FullTypeString);
  376. }
  377. else
  378. {
  379. rawMessageType = deviceHandlerInstance.GetType().GetInterfaces().Where(i => i.Name == typeof(IDeviceHandler<,>).Name).FirstOrDefault()?.GetGenericArguments()?.FirstOrDefault();
  380. }
  381. if (rawMessageType == null)
  382. throw new ArgumentException("Failed for resolving MetaParts: RawMessageType from Type: " + deviceHandlerInstance.GetType().FullName);
  383. #endregion
  384. #region Create Parts of Message Type
  385. Type messageType = null;
  386. if (!string.IsNullOrEmpty(metaConfig?.Parts?.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.MessageTypeStr)?.FullTypeString))
  387. {
  388. messageType = Type.GetType(metaConfig?.Parts?.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.MessageTypeStr)?.FullTypeString);
  389. }
  390. else
  391. {
  392. messageType = deviceHandlerInstance.GetType().GetInterfaces().Where(i => i.Name == typeof(IDeviceHandler<,>).Name).FirstOrDefault()?.GetGenericArguments()?.LastOrDefault();
  393. }
  394. if (messageType == null)
  395. throw new ArgumentException("Failed for resolving MetaParts: MessageType from Type: " + deviceHandlerInstance.GetType().FullName);
  396. #endregion
  397. #region Create Parts of Parser Instance
  398. object parserInstance = null;
  399. if (!string.IsNullOrEmpty(metaConfig?.Parts?.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.Parser)?.FullTypeString))
  400. {
  401. parserInstance = ObjectInstanceCreator.Create(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.Parser).FullTypeString,
  402. null,
  403. JsonDocument.Parse(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.Parser).ParametersJsonArrayStr ?? "[]").RootElement.EnumerateArray().ToArray(),
  404. dependencies);
  405. }
  406. else
  407. {
  408. var metaPartsAttri = deviceHandlerInstance.GetType().GetCustomAttributes<MetaPartsRequired>()?.FirstOrDefault(at => typeof(ParserBase).IsAssignableFrom(at.RequiredPartsType));
  409. if (metaPartsAttri == null)
  410. {
  411. var searchedParserType = deviceHandlerInstance.GetType().Assembly.GetTypes()
  412. .FirstOrDefault(t => typeof(ParserBase).IsAssignableFrom(t));
  413. if (searchedParserType == null)
  414. throw new ArgumentException("Failed to Search Parser from Type: " + deviceHandlerInstance.GetType().FullName);
  415. else
  416. parserInstance = ObjectInstanceCreator.Create(searchedParserType?.AssemblyQualifiedName,
  417. null,
  418. new JsonElement[] { },
  419. dependencies);
  420. }
  421. else
  422. parserInstance = ObjectInstanceCreator.Create(metaPartsAttri.RequiredPartsType.FullName,
  423. null,
  424. metaPartsAttri.DefaultCtorParamsJsonStrings.Select(js => JsonDocument.Parse(js).RootElement).ToArray(),
  425. //JsonDocument.Parse(metaPartsAttri.DefaultCtorParamsJsonStrings ?? "[]").RootElement.EnumerateArray().ToArray(),
  426. dependencies);
  427. }
  428. if (parserInstance == null)
  429. throw new ArgumentException("Failed for resolving Parser from Type: " + deviceHandlerInstance.GetType().FullName);
  430. #endregion
  431. #region Create Parts of MessageCutter Instance
  432. object messageCutterInstance = null;
  433. if (!string.IsNullOrEmpty(metaConfig?.Parts?.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.MessageCutter)?.FullTypeString))
  434. {
  435. messageCutterInstance = ObjectInstanceCreator.Create(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.MessageCutter).FullTypeString,
  436. null,
  437. JsonDocument.Parse(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.MessageCutter).ParametersJsonArrayStr ?? "[]").RootElement.EnumerateArray().ToArray(),
  438. dependencies);
  439. }
  440. else
  441. {
  442. var metaPartsAttri = deviceHandlerInstance.GetType().GetCustomAttributes<MetaPartsRequired>()?.FirstOrDefault(at => at.RequiredPartsType?.GetInterfaces().Any(i => i.Name == typeof(IMessageCutter<>).Name) ?? false);
  443. if (metaPartsAttri == null)
  444. {
  445. var searchedMessageCutterType = deviceHandlerInstance.GetType().Assembly.GetTypes()
  446. .FirstOrDefault(t => t.GetInterfaces().Any(i => i.Name == typeof(IMessageCutter<>).Name));
  447. if (searchedMessageCutterType == null)
  448. throw new ArgumentException("Failed to Search MessageCutter from Type: " + deviceHandlerInstance.GetType().FullName);
  449. else
  450. messageCutterInstance = ObjectInstanceCreator.Create(searchedMessageCutterType.AssemblyQualifiedName,
  451. null,
  452. new JsonElement[] { },
  453. dependencies);
  454. }
  455. else
  456. messageCutterInstance = ObjectInstanceCreator.Create(metaPartsAttri.RequiredPartsType.FullName,
  457. null,
  458. metaPartsAttri.DefaultCtorParamsJsonStrings.Select(js => JsonDocument.Parse(js).RootElement).ToArray(),
  459. dependencies);
  460. if (messageCutterInstance == null)
  461. throw new ArgumentException("Failed for resolving MessageCutter from Type: " + deviceHandlerInstance.GetType().FullName);
  462. }
  463. #endregion
  464. var communicatorInstance = ObjectInstanceCreator.Create(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.Communicator).FullTypeString,
  465. new Type[] { messageType },
  466. JsonDocument.Parse(metaConfig.Parts.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.Communicator).ParametersJsonArrayStr ?? "[]").RootElement.EnumerateArray().ToArray(),
  467. dependencies.Concat(new object[] { parserInstance, messageCutterInstance }).ToArray());
  468. if (communicatorInstance == null)
  469. throw new ArgumentException("Failed for resolving Communicator from Type: " + deviceHandlerInstance.GetType().FullName);
  470. #region Create Final Processor Instance
  471. if (!string.IsNullOrEmpty(metaConfig?.Parts?.FirstOrDefault(p => p.Type == ProcessorMetaPartsTypeEnum.DeviceProcessor)?.FullTypeString))
  472. {
  473. //if (Type.GetType(metaConfig.Parts.First(p => p.Type == ProcessorPartsTypeEnum.Processor).FullTypeString).IsGenericType)
  474. //{
  475. processorInstance = (T)ObjectInstanceCreator.Create(metaConfig.Parts.First(p => p.Type == ProcessorMetaPartsTypeEnum.DeviceProcessor).FullTypeString,
  476. new Type[] { rawMessageType, messageType },
  477. JsonDocument.Parse(metaConfig.Parts.First(p => p.Type == ProcessorMetaPartsTypeEnum.DeviceProcessor).ParametersJsonArrayStr ?? "[]").RootElement.EnumerateArray().ToArray(),
  478. dependencies.Concat(new object[] { parserInstance, messageCutterInstance, communicatorInstance, deviceHandlerInstance }).ToArray());
  479. //}
  480. //else
  481. //{
  482. // processorInstance = (T)Create(metaConfig.Parts.First(p => p.Type == ProcessorPartsTypeEnum.Processor).FullTypeString,
  483. // null,
  484. // JsonDocument.Parse(metaConfig.Parts.First(p => p.Type == ProcessorPartsTypeEnum.Processor).ParametersJsonArrayStr ?? "[]").RootElement.EnumerateArray().ToArray(),
  485. // parts.Concat(new object[] { parserInstance, messageCutterInstance, communicatorInstance, deviceHandlerInstance }).ToArray());
  486. //}
  487. }
  488. else
  489. {
  490. var metaPartsAttri = deviceHandlerInstance.GetType().GetCustomAttributes<MetaPartsRequired>()?.FirstOrDefault(at => at.RequiredPartsType.GetInterfaces().Any(i => i.Name == typeof(IDeviceProcessor<,>).Name));
  491. if (metaPartsAttri == null)
  492. throw new ArgumentException("Failed for resolving MetaParts: DeviceProcessor from Type: " + deviceHandlerInstance.GetType().FullName);
  493. processorInstance = (T)ObjectInstanceCreator.Create(metaPartsAttri.RequiredPartsType.FullName,
  494. new Type[] { rawMessageType, messageType },
  495. metaPartsAttri.DefaultCtorParamsJsonStrings.Select(js => JsonDocument.Parse(js).RootElement).ToArray(),
  496. dependencies.Concat(new object[] { parserInstance, messageCutterInstance, communicatorInstance, deviceHandlerInstance }).ToArray());
  497. }
  498. #endregion
  499. }
  500. if (processorInstance != null)
  501. {
  502. processorInstance.MetaConfigName = metaConfig.Name;
  503. //processorInstance.SerialNumber = Guid.NewGuid().ToString();
  504. return (T)processorInstance;
  505. }
  506. throw new InvalidOperationException("Can't Create Processor for processorMetaConfig: " + metaConfig.Name + Environment.NewLine + (metaConfig.Description ?? ""));
  507. }
  508. }
  509. }