CompositeState.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. namespace Wayne.Lib.StateEngine.Generic
  2. {
  3. /// <summary>
  4. /// Generic composite state class that has a main object of a generic type.
  5. /// </summary>
  6. /// <typeparam name="TMain">Specifies the type of the main object.</typeparam>
  7. /// <typeparam name="TData">Specifies the type of state data the state uses.</typeparam>
  8. public abstract class CompositeState<TMain, TData> : CompositeState<TMain>, IStateWithData where TData : StateData
  9. {
  10. #region Fields
  11. private TData data;
  12. private IStateWithData stateWithData;
  13. #endregion
  14. #region Properties
  15. /// <summary>
  16. /// Gets the state data for this state.
  17. /// </summary>
  18. protected TData Data
  19. {
  20. get
  21. {
  22. if (data != null) // Do I have my own data?
  23. return data;
  24. else // Otherwise, unwind from parent composite states.
  25. return stateWithData.StateData as TData;
  26. }
  27. }
  28. StateData IStateWithData.StateData
  29. {
  30. get { return Data; }
  31. }
  32. #endregion
  33. #region Methods
  34. internal override void PerformEnter(StateEntry stateEntry, ref Transition transition)
  35. {
  36. InitStateData();
  37. base.PerformEnter(stateEntry, ref transition);
  38. }
  39. internal override void PerformExit()
  40. {
  41. base.PerformExit();
  42. using (data) //Dispose without risk for nullref exceptions
  43. {
  44. data = null;
  45. }
  46. }
  47. /// <summary>
  48. /// CreateStateData method should be overridden by those composite states that does not have the same state data
  49. /// as their parent state.
  50. /// </summary>
  51. /// <param name="parentStateData"></param>
  52. /// <returns></returns>
  53. protected virtual TData CreateStateData(StateData parentStateData)
  54. {
  55. return null;
  56. }
  57. private void InitStateData()
  58. {
  59. //Create the state data for this composite state.
  60. //The composite state has the option to return null, if it wants to use a parent composite state's data object.
  61. var compositeStateWithData = ParentState as IStateWithData;
  62. if (compositeStateWithData != null)
  63. data = CreateStateData(compositeStateWithData.StateData); //Create state data before enter method of state gets called.
  64. else
  65. data = CreateStateData(null);
  66. if (data == null)
  67. {
  68. if (stateWithData == null)
  69. {
  70. stateWithData = StateData.GetParentCompositeStateWithStateData<TData>(this);
  71. }
  72. }
  73. }
  74. #endregion
  75. }
  76. }