MatchIntentRegistry.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * Copyright (c) Meta Platforms, Inc. and affiliates.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the license found in the
  6. * LICENSE file in the root directory of this source tree.
  7. */
  8. using System;
  9. using System.Reflection;
  10. using System.Threading;
  11. using Meta.WitAi.Utilities;
  12. using UnityEngine;
  13. namespace Meta.WitAi
  14. {
  15. internal class RegisteredMatchIntent
  16. {
  17. public Type type;
  18. public MethodInfo method;
  19. public MatchIntent matchIntent;
  20. }
  21. internal static class MatchIntentRegistry
  22. {
  23. private static DictionaryList<string, RegisteredMatchIntent> registeredMethods;
  24. public static DictionaryList<string, RegisteredMatchIntent> RegisteredMethods
  25. {
  26. get
  27. {
  28. if (null == registeredMethods)
  29. {
  30. // Note, first run this will not return any values. Initialize
  31. // scans assemblies on a different thread. This is ok for voice
  32. // commands since they are generally executed in realtime after
  33. // initialization is complete. This is a perf optimization.
  34. //
  35. // Best practice is to call Initialize in Awake of any method
  36. // that will be using the resulting data.
  37. Initialize();
  38. }
  39. return registeredMethods;
  40. }
  41. }
  42. internal static void Initialize()
  43. {
  44. if (null != registeredMethods) return;
  45. registeredMethods = new DictionaryList<string, RegisteredMatchIntent>();
  46. new Thread(RefreshAssemblies).Start();
  47. }
  48. internal static void RefreshAssemblies()
  49. {
  50. if (Thread.CurrentThread.ThreadState == ThreadState.Aborted)
  51. {
  52. return;
  53. }
  54. // TODO: We could potentially build this list at compile time and cache it
  55. // Work on a local dictionary to avoid thread complications
  56. var dictionary = new DictionaryList<string, RegisteredMatchIntent>();
  57. foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
  58. {
  59. try {
  60. foreach (Type t in assembly.GetTypes()) {
  61. try {
  62. foreach (var method in t.GetMethods()) {
  63. try {
  64. foreach (var attribute in method.GetCustomAttributes(typeof(MatchIntent))) {
  65. try {
  66. var mi = (MatchIntent)attribute;
  67. dictionary[mi.Intent].Add(new RegisteredMatchIntent() {
  68. type = t,
  69. method = method,
  70. matchIntent = mi
  71. });
  72. } catch (Exception e) {
  73. VLog.E(e);
  74. }
  75. }
  76. } catch (Exception e) {
  77. VLog.E(e);
  78. }
  79. }
  80. } catch (Exception e) {
  81. VLog.E(e);
  82. }
  83. }
  84. } catch (Exception e) {
  85. VLog.E(e);
  86. }
  87. }
  88. registeredMethods = dictionary;
  89. }
  90. }
  91. }