public void Super(string behavior) { if (next == null) { throw new InvalidOperationException($"Super behavior can only be specified while behavior configuration is in progress. " + $"Current: {Current}, Offending: {behavior}"); } if (next.Includes(behavior)) { throw new InvalidOperationException("Detected cyclic declaration of super behaviors. " + $"'{behavior}' is already within super chain of {next.Name}"); } var existent = current.FindSuper(behavior); if (existent != null) { next.Super(existent); return; } var prev = next; next = new CustomBehavior(behavior); prev.Super(next); var action = RegisteredAction(behavior); action(actor); next = prev; }
public void Super(CustomBehavior super) { if (this.super != null) { throw new InvalidOperationException($"Super '{this.super.Name}' has been already configured for behavior '{Name}'"); } this.super = super; super.sub = this; }
public async Task Become(string behavior) { if (IsNull()) { throw new InvalidOperationException("Initial behavior should be set before calling Become"); } if (next != null) { throw new InvalidOperationException($"Become cannot be called again while behavior configuration is in progress.\n" + $"Current: {Current}, In-progress: {next.Name}, Offending: {behavior}"); } if (Current == behavior) { throw new InvalidOperationException($"Actor is already behaving as '{behavior}'"); } var action = RegisteredAction(behavior); next = new CustomBehavior(behavior); action(actor); var transition = new Transition(current, next); try { await actor.OnTransitioning(transition); await current.HandleDeactivate(transition); await current.HandleUnbecome(transition); current = next; await current.HandleBecome(transition); next = null; // now become could be re-entered ... await current.HandleActivate(transition); // ... and we can signal about successful transition await actor.OnTransitioned(transition); } catch (Exception exception) { await actor.OnTransitionFailure(transition, exception); actor.Activation.DeactivateOnIdle(); ExceptionDispatchInfo.Capture(exception).Throw(); } }
public void Initial(string behavior) { if (!IsNull()) { throw new InvalidOperationException($"Initial behavior has been already set to '{Current}'"); } var action = RegisteredAction(behavior); next = new CustomBehavior(behavior); action(actor); current = next; next = null; }
static CustomBehavior() { Null = new CustomBehavior(); Null.OnActivate(() => Task.CompletedTask); Null.OnDeactivate(() => Task.CompletedTask); Null.OnReceive((actor, message) => actor.Dispatch(message)); Null.OnReminder((actor, id) => { throw new NotImplementedException( $"Override {nameof(Actor.OnReminder)}(string id) method in " + $"class {actor.GetType()} to implement corresponding behavior"); }); const string warn = "Initial behavior has not been set"; Null.OnBecome(() => { throw new InvalidOperationException(warn); }); }
internal Transition(CustomBehavior from, CustomBehavior to) { this.from = from; this.to = to; }
bool IncludedIn(CustomBehavior behavior) => behavior?.FindSuper(Name) != null;
bool Includes(CustomBehavior behavior) => this == behavior || (sub?.Includes(behavior) ?? false);