///<summary>Combines two souls by using a custom function to combine their phases.</summary> public static ISoul Combine(this ISoul soul1, ISoul soul2, Func <Phase, Phase, Phase> phaseCombiner) { Func <Phase> getPhase = () => phaseCombiner(soul1.Phase, soul2.Phase); return(new AnonymousSoul( getPhase, action => { Func <bool> tryComplete = () => { var hasPhase = getPhase() != Phase.Mortal; if (hasPhase) { action(); } return hasPhase; }; return soul1.InterdependentRegister(tryComplete, soul2, tryComplete); })); }
///<summary>Registers a callback to the dependent soul that only occurs if the necessary soul doesn't die first, ensuring everything is cleaned up properly.</summary> public static RegistrationRemover DependentRegister(this ISoul soul, Action action, ISoul necessarySoul) { if (soul == null) { throw new ArgumentNullException("soul"); } if (action == null) { throw new ArgumentNullException("action"); } if (necessarySoul == null) { throw new ArgumentNullException("necessarySoul"); } // when the necessary soul is the same soul as the dependent soul, assume the callback invocation will beat the registration removal if (ReferenceEquals(soul, necessarySoul)) { necessarySoul = ImmortalSoul.Instance; } // avoid wrapping when possible if (necessarySoul.Phase == Phase.Dead) { return(EmptyRemover); } if (soul.Phase != Phase.Mortal) { action(); return(EmptyRemover); } if (necessarySoul.Phase == Phase.Immortal) { return(soul.Register(action)); } return(soul.InterdependentRegister( () => { action(); return true; }, necessarySoul, () => necessarySoul.Phase == Phase.Dead)); }