publicvirtual StateDefinition ReverseOn(paramsstring[] terms) { Check.NotNullOrEmpty(terms, nameof(terms)); var lastTransition = Transitions.LastOrDefault(); if (lastTransition == null) { thrownew MyStatesException("No state transition to be reversed."); }
publicoverrideboolEquals(object obj) { if (obj == null) returnfalse; if (ReferenceEquals(this, obj)) returntrue; if (!obj.GetType().IsAssignableTo<StateDefinition>()) returnfalse;
protectedvirtualvoidAssertStateAllowTransitFrom(StateDefinition sourceState) { if (sourceState.Type.HasFlag(StateType.Final)) { thrownew MyStatesException("Final state cannot be transited from.", sourceState.Name); } }
protectedvirtualvoidAssertStateAllowTransitTo(StateDefinition targetState) { if (targetState.Type.HasFlag(StateType.Initial)) { thrownew MyStatesException("Initial state cannot be transited to.", targetState.Name); }
if (Terms.IsNullOrEmpty()) { thrownew MyStatesException("State transition must have terms.", targetState.Name); }
if (SourceState.HasTargetState(targetState)) { thrownew MyStatesException("Source state already has a same target state.", targetState.Name); }
if (SourceState.Transitions .SelectMany(transition => transition.Terms) .Intersect(Terms) .Any()) { thrownew MyStatesException("Source state cannot have multiple transitions with same terms", targetState.Name); } }
protectedvirtualvoidAssertTransitionAllowReverse() { if (SourceState == null || TargetState == null) { thrownew MyStatesException($"{nameof(SourceState)} and {nameof(TargetState)} should not be null when reversing."); }
publicvirtual StateGroupDefinition AddGroup( string name, ILocalizableString displayName = null) { if (Name == name || _groups.Any(group => group.Name == name)) { thrownew MyStatesException($"There is already an existing state group definition with given name: {name}", stateGroupName: name); }
vargroup = new StateGroupDefinition(name, displayName, this);
_groups.Add(group); returngroup; }
publicvirtual StateDefinition AddState( string name, ILocalizableString displayName = null, StateType type = StateType.Intermediate) { var state = new StateDefinition(name, displayName, type); return AddState(state); }
publicvirtual StateDefinition AddState(StateDefinition state) { if (_states.Any(s => s.Name == Check.NotNull(state, nameof(state)).Name)) { thrownew MyStatesException($"There is already an existing state definition with given name: {state.Name}", state.Name, Name); }
vargroup = DefinationManager.GetGroupRecursively(groupName); var transitions = GetTransitionsToHandle(group, term); var context = new StateTransitionContext(groupName, term, transitions, recurse); contextAction?.Invoke(context);
usingvar scope = ServiceProvider.CreateScope();
var handlers = Options .TransitionHandlers .Where(handler => { var handleGroupName = HandleStateAttribute.GetHandleGroupName(handler); return handleGroupName.IsNullOrEmpty() || DefinationManager.IsGroupBelongTo(groupName, handleGroupName); }) .Select(p => scope.ServiceProvider.GetRequiredService(p) as IStateTransitionHandler) .ToList();
foreach (var handler in handlers) { await handler.HandleAsync(context);
if (!context.HandlerContext.Any(handlerContext => !handlerContext.Value)) { break; } }
if (!context.HandlerContext.Any(handlerContext => handlerContext.Value)) { Logger.LogWarning("State transition notification not handled by any of the registered handlers, context: {Context}", context); } }
privatestaticvoidAutoAddDefinitionProviders(IServiceCollection services) { var definitionProviders = new List<Type>(); var transitionHandlers = new List<Type>();
services.OnRegistred(context => { if (typeof(IStateDefinitionProvider).IsAssignableFrom(context.ImplementationType)) { definitionProviders.Add(context.ImplementationType); }
if (typeof(IStateTransitionHandler).IsAssignableFrom(context.ImplementationType)) { transitionHandlers.Add(context.ImplementationType); } });