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
}
}