namespace Wayne.Lib.StateEngine.Generic { /// /// Generic composite state class that has a main object of a generic type. /// /// Specifies the type of the main object. /// Specifies the type of state data the state uses. public abstract class CompositeState : CompositeState, IStateWithData where TData : StateData { #region Fields private TData data; private IStateWithData stateWithData; #endregion #region Properties /// /// Gets the state data for this state. /// protected TData Data { get { if (data != null) // Do I have my own data? return data; else // Otherwise, unwind from parent composite states. return stateWithData.StateData as TData; } } StateData IStateWithData.StateData { get { return Data; } } #endregion #region Methods internal override void PerformEnter(StateEntry stateEntry, ref Transition transition) { InitStateData(); base.PerformEnter(stateEntry, ref transition); } internal override void PerformExit() { base.PerformExit(); using (data) //Dispose without risk for nullref exceptions { data = null; } } /// /// CreateStateData method should be overridden by those composite states that does not have the same state data /// as their parent state. /// /// /// protected virtual TData CreateStateData(StateData parentStateData) { return null; } private void InitStateData() { //Create the state data for this composite state. //The composite state has the option to return null, if it wants to use a parent composite state's data object. var compositeStateWithData = ParentState as IStateWithData; if (compositeStateWithData != null) data = CreateStateData(compositeStateWithData.StateData); //Create state data before enter method of state gets called. else data = CreateStateData(null); if (data == null) { if (stateWithData == null) { stateWithData = StateData.GetParentCompositeStateWithStateData(this); } } } #endregion } }