CompositeState.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #region --------------- Copyright Dresser Wayne Pignone -------------
  2. /*
  3. * $Log: /Wrk/WayneLibraries/Wrk/StateEngine/CompositeState.cs $
  4. *
  5. * 7 08-03-25 14:15 Mattias.larsson
  6. * Clean-up.
  7. *
  8. * 6 08-02-26 14:06 Mattias.larsson
  9. * Renamed stateName to factoryName.
  10. *
  11. * 5 07-08-15 15:27 roger.månsson
  12. * Added SetDebugLogger method.
  13. *
  14. * 4 07-08-07 8:26 Mattias.larsson
  15. *
  16. * 3 07-03-02 13:19 roger.månsson
  17. */
  18. #endregion
  19. #region Old file header
  20. /*===============================================================================
  21. * CompositeState
  22. *
  23. * Change history
  24. * When Who Comment
  25. * ---------- ------ ------------------------------------
  26. * 2006-07-17 RMa Major updates, Changed state machine and event handling.
  27. * 2006-05-09 RMa Implemented the dispose handling.
  28. * 2006-03-01 RMa FXCop updates: CreateStateMachine is not virtual anymore.
  29. * 2006-02-03 RMa FXCop updates: Made constuctor protected + misc.
  30. * 2006-01-27 RMa Removed interface Event. Use Event class instead.
  31. * 2006-01-05 RMa Added the internal function LookupState
  32. * 2005-12-14 RMa Changed so Internal_Enter is called by the state machine, so we are sure that
  33. * the internal stuff gets called ,if the user forgets to call base.Enter()....
  34. * 2005-12-09 RMa Fixed so the state entry always is sent into a composite state machine.
  35. * 2005-12-05 RMa This header added.
  36. *
  37. ---------------------------------------------------------------------------------*/
  38. #endregion
  39. using System;
  40. using Wayne.Lib.Log;
  41. namespace Wayne.Lib.StateEngine
  42. {
  43. /// <summary>
  44. /// Composite state is an abstract class that should be overriden to
  45. /// create a state that within itself have a state machine with sub states.
  46. /// When creating the composite state, a message handling thread should be sent
  47. /// in to the composite state constructor. It can either be a new thread if the
  48. /// composite state machine should run in a separate thread , or the thread of the
  49. /// parent state machine if the machine should run in the same thread.
  50. /// </summary>
  51. abstract public class CompositeState : State
  52. {
  53. #region Fields
  54. private StateMachine stateMachine;
  55. private bool disposed;
  56. #endregion
  57. #region Construction
  58. /// <summary>
  59. /// Initializes a new instance of a composite state.
  60. /// </summary>
  61. protected CompositeState()
  62. {
  63. stateMachine = new CompositeStateMachine(this);
  64. }
  65. /// <summary>
  66. /// Destructor
  67. /// </summary>
  68. ~CompositeState()
  69. {
  70. Dispose(false);
  71. }
  72. #endregion
  73. #region Methods
  74. /// <summary>
  75. /// Handles an incoming event.
  76. /// </summary>
  77. /// <param name="stateEngineEvent">Event that is received.</param>
  78. /// <param name="transition">Perform a transaction by assigning a transition object to this ref parameter.</param>
  79. protected sealed override void HandleEvent(StateEngineEvent stateEngineEvent, ref Transition transition)
  80. {
  81. BeforeHandleEvent(stateEngineEvent, ref transition);
  82. if (!stateEngineEvent.Handled)
  83. stateMachine.HandleEvent(stateEngineEvent, ref transition);
  84. if (!stateEngineEvent.Handled)
  85. UnhandledEvent(stateEngineEvent, ref transition);
  86. }
  87. /// <summary>
  88. /// Method that can be overriden in descendant classes, so events can be handed before they are sent to the
  89. /// state machine.
  90. /// </summary>
  91. /// <param name="stateEngineEvent"></param>
  92. /// <param name="transition">Perform a transaction by assigning a transition object to this ref parameter.</param>
  93. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")]
  94. public virtual void BeforeHandleEvent(StateEngineEvent stateEngineEvent, ref Transition transition)
  95. {
  96. }
  97. /// <summary>
  98. /// Method that can be overriden if wanting to handle events that not has been handled in the composite state machine.
  99. /// </summary>
  100. /// <param name="stateEngineEvent"></param>
  101. /// <param name="transition">Perform a transaction by assigning a transition object to this ref parameter.</param>
  102. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")]
  103. public virtual void UnhandledEvent(StateEngineEvent stateEngineEvent, ref Transition transition)
  104. {
  105. }
  106. #endregion
  107. #region Internal Methods
  108. internal override void PerformEnter(StateEntry entry, ref Transition transition)
  109. {
  110. base.PerformEnter(entry, ref transition);
  111. if (!stateMachine.Initialized)
  112. this.Initialize();
  113. //If base did not result in any transition,
  114. if (transition == null)
  115. {
  116. stateMachine.EnterState(entry, ref transition);
  117. if (transition != null)
  118. stateMachine.HandleTransition(ref transition);
  119. }
  120. }
  121. internal override void PerformExit()
  122. {
  123. base.PerformExit();
  124. stateMachine.ExitState();
  125. }
  126. /// <summary>
  127. /// Initializes and creates the states of the composite state engine.
  128. /// </summary>
  129. internal void Initialize()
  130. {
  131. if (!stateMachine.Initialized)
  132. stateMachine.Initialize();
  133. }
  134. /// <summary>
  135. /// This function is used to locate a specific state in the state machine.
  136. ///
  137. /// The composite state checks first if its own FactoryName matches the name,
  138. /// if not it calls each created state subsequently.
  139. /// </summary>
  140. /// <param name="factoryName">The name of the state that should be looked up.</param>
  141. /// <returns>True if the state is or contains a state with this name.</returns>
  142. internal override bool LookupState(string factoryName)
  143. {
  144. if (base.LookupState(factoryName))
  145. return true;
  146. foreach (State state in StateMachine.CreatedStates)
  147. {
  148. if (state.LookupState(factoryName))
  149. return true;
  150. }
  151. return false;
  152. }
  153. /// <summary>
  154. /// Internal dispose method.
  155. /// </summary>
  156. /// <param name="disposing"></param>
  157. protected override void Dispose(bool disposing)
  158. {
  159. try
  160. {
  161. if (!disposed)
  162. {
  163. disposed = true;
  164. if (disposing)
  165. stateMachine.Dispose();
  166. }
  167. }
  168. finally
  169. {
  170. base.Dispose(disposing);
  171. }
  172. }
  173. #endregion
  174. #region Properties
  175. /// <summary>
  176. /// Returns the state machine that is used with the Composite state.
  177. /// </summary>
  178. public StateMachine StateMachine
  179. {
  180. get { return stateMachine; }
  181. }
  182. /// <summary>
  183. /// Set the parent state machine for the state.
  184. /// </summary>
  185. internal override void SetParentStateMachine(StateMachine parentStateMachine)
  186. {
  187. base.SetParentStateMachine(parentStateMachine);
  188. this.stateMachine.ParentStateMachine = parentStateMachine;
  189. }
  190. /// <summary>
  191. /// Set the debug logger for the composite state, and assign it on to the state machine.
  192. /// </summary>
  193. /// <param name="debugLogger"></param>
  194. /// <param name="logCategory"></param>
  195. internal override void SetDebugLogger(IDebugLogger debugLogger, object logCategory)
  196. {
  197. base.SetDebugLogger(debugLogger, logCategory);
  198. this.stateMachine.SetDebugLogger(debugLogger, logCategory);
  199. }
  200. #endregion
  201. }
  202. }