OptionsServiceImpl.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. namespace SRDebugger.Services.Implementation
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.ObjectModel;
  6. using Internal;
  7. using SRF.Service;
  8. using SRF.Helpers;
  9. using UnityEngine;
  10. [Service(typeof (IOptionsService))]
  11. public partial class OptionsServiceImpl : IOptionsService
  12. {
  13. public event EventHandler OptionsUpdated;
  14. public ICollection<OptionDefinition> Options
  15. {
  16. get { return _optionsReadonly; }
  17. }
  18. private void OptionsContainerOnOptionAdded(IOptionContainer container, OptionDefinition optionDefinition)
  19. {
  20. List<OptionDefinition> options;
  21. if(!_optionContainerLookup.TryGetValue(container, out options))
  22. {
  23. Debug.LogWarning("[SRDebugger] Received event from unknown option container.");
  24. return;
  25. }
  26. if (options.Contains(optionDefinition))
  27. {
  28. Debug.LogWarning("[SRDebugger] Received option added event from option container, but option has already been added.");
  29. return;
  30. }
  31. options.Add(optionDefinition);
  32. _options.Add(optionDefinition);
  33. OnOptionsUpdated();
  34. }
  35. private void OptionsContainerOnOptionRemoved(IOptionContainer container, OptionDefinition optionDefinition)
  36. {
  37. List<OptionDefinition> options;
  38. if (!_optionContainerLookup.TryGetValue(container, out options))
  39. {
  40. Debug.LogWarning("[SRDebugger] Received event from unknown option container.");
  41. return;
  42. }
  43. if (options.Remove(optionDefinition))
  44. {
  45. _options.Remove(optionDefinition);
  46. OnOptionsUpdated();
  47. }
  48. else
  49. {
  50. Debug.LogWarning("[SRDebugger] Received option removed event from option container, but option does not exist.");
  51. }
  52. }
  53. private readonly Dictionary<IOptionContainer, List<OptionDefinition>> _optionContainerLookup = new Dictionary<IOptionContainer, List<OptionDefinition>>();
  54. private readonly Dictionary<IOptionContainer, OptionContainerEventHandler> _optionContainerEventHandlerLookup = new Dictionary<IOptionContainer, OptionContainerEventHandler>();
  55. private readonly List<OptionDefinition> _options = new List<OptionDefinition>();
  56. private readonly IList<OptionDefinition> _optionsReadonly;
  57. public OptionsServiceImpl()
  58. {
  59. _optionsReadonly = new ReadOnlyCollection<OptionDefinition>(_options);
  60. }
  61. public void Scan(object obj)
  62. {
  63. AddContainer(obj);
  64. }
  65. public void AddContainer(object obj)
  66. {
  67. var container = obj as IOptionContainer ?? new ReflectionOptionContainer(obj);
  68. AddContainer(container);
  69. }
  70. public void AddContainer(IOptionContainer optionContainer)
  71. {
  72. if (_optionContainerLookup.ContainsKey(optionContainer))
  73. {
  74. throw new Exception("An options container should only be added once.");
  75. }
  76. List<OptionDefinition> options = new List<OptionDefinition>();
  77. options.AddRange(optionContainer.GetOptions());
  78. _optionContainerLookup.Add(optionContainer, options);
  79. if (optionContainer.IsDynamic)
  80. {
  81. var handler = new OptionContainerEventHandler(this, optionContainer);
  82. _optionContainerEventHandlerLookup.Add(optionContainer, handler);
  83. }
  84. if (options.Count > 0)
  85. {
  86. _options.AddRange(options);
  87. OnOptionsUpdated();
  88. }
  89. }
  90. public void RemoveContainer(object obj)
  91. {
  92. var container = obj as IOptionContainer ?? new ReflectionOptionContainer(obj);
  93. RemoveContainer(container);
  94. }
  95. public void RemoveContainer(IOptionContainer optionContainer)
  96. {
  97. if (!_optionContainerLookup.ContainsKey(optionContainer))
  98. {
  99. return;
  100. }
  101. bool isDirty = false;
  102. var list = _optionContainerLookup[optionContainer];
  103. _optionContainerLookup.Remove(optionContainer);
  104. foreach (var op in list)
  105. {
  106. _options.Remove(op);
  107. isDirty = true;
  108. }
  109. OptionContainerEventHandler handler;
  110. if (_optionContainerEventHandlerLookup.TryGetValue(optionContainer,
  111. out handler))
  112. {
  113. handler.Dispose();
  114. _optionContainerEventHandlerLookup.Remove(optionContainer);
  115. }
  116. if (isDirty)
  117. {
  118. OnOptionsUpdated();
  119. }
  120. }
  121. private void OnOptionsUpdated()
  122. {
  123. if (OptionsUpdated != null)
  124. {
  125. OptionsUpdated(this, EventArgs.Empty);
  126. }
  127. }
  128. class OptionContainerEventHandler : IDisposable
  129. {
  130. private readonly OptionsServiceImpl _service;
  131. private readonly IOptionContainer _container;
  132. public OptionContainerEventHandler(OptionsServiceImpl service, IOptionContainer container)
  133. {
  134. _container = container;
  135. _service = service;
  136. container.OptionAdded += ContainerOnOptionAdded;
  137. container.OptionRemoved += ContainerOnOptionRemoved;
  138. }
  139. private void ContainerOnOptionAdded(OptionDefinition obj)
  140. {
  141. _service.OptionsContainerOnOptionAdded(_container, obj);
  142. }
  143. private void ContainerOnOptionRemoved(OptionDefinition obj)
  144. {
  145. _service.OptionsContainerOnOptionRemoved(_container, obj);
  146. }
  147. public void Dispose()
  148. {
  149. _container.OptionAdded -= ContainerOnOptionAdded;
  150. _container.OptionRemoved -= ContainerOnOptionRemoved;
  151. }
  152. }
  153. }
  154. }