/// <summary> /// Configures transition guard based on specified list user of roles. /// </summary> /// <typeparam name="TState">The type of the state.</typeparam> /// <typeparam name="TActivity">The type of the activity.</typeparam> /// <param name="stateConfig">The state configuration.</param> /// <param name="trigger">The trigger.</param> /// <param name="destinationState">State of the destination.</param> /// <param name="roleGuard">The actor guard, use this.PermitFor() helper method to define list of permitted roles.</param> /// <returns></returns> public static StateMachine <TState, TActivity> .StateConfiguration PermitForActors <TState, TActivity>( this StateMachine <TState, TActivity> .StateConfiguration stateConfig, TActivity trigger, TState destinationState, TransitionGuard roleGuard) { return(stateConfig .PermitIf(trigger, destinationState, roleGuard.GuardMethod, roleGuard.Description)); }
/// <summary> /// Permits the trigger only if all conditions are met. /// </summary> /// <typeparam name="TState">The type of the state.</typeparam> /// <typeparam name="TActivity">The type of the activity.</typeparam> /// <param name="stateConfig">The state configuration.</param> /// <param name="trigger">The trigger.</param> /// <param name="destinationState">State of the destination.</param> /// <param name="actorGuard">The role guard.</param> /// <param name="guards">The guards.</param> /// <returns>State machine configuration</returns> public static StateMachine <TState, TActivity> .StateConfiguration PermitOnlyIf <TState, TActivity>( this StateMachine <TState, TActivity> .StateConfiguration stateConfig, TActivity trigger, TState destinationState, TransitionGuard actorGuard, params Func <bool>[] guards) { var listOfGuards = new List <TransitionGuard>(new[] { actorGuard }); var otherGuards = guards .Select(g => new TransitionGuard(g, g.Method.Name)) .ToList(); listOfGuards .AddRange(otherGuards); //var triggerName = trigger.ToString(); //var destinationStateName = destinationState.ToString(); //var currentStateName = stateConfig.State.ToString(); Func <bool> aggregateGuardExpression = () => { var failedGuards = listOfGuards .Where(g => !g.GuardMethod()) .Select(g => g.Description) .ToArray(); return (!failedGuards.Any()); // THIS MIGHT NOT WORK WELL WITH MULTIPLE DESTINATIONS // FOR SAME TRIGGER BECAUSE OTHER VALID GUARD MIGHT NOT // HAVE CHANCE TO BE EVALUATED BECAUSE OF THIS EXCEPTION // ON THE OTHER HAND THIS GIVES US EXACT REPORT OF FAILED CONDITIONS // Alternative is to "return false" here but get more generic exeption; // throw new UnmetTransitionGuardsException(currentStateName, triggerName, destinationStateName, failedGuards); // return true; }; var otherGuardsSummary = otherGuards .Select(g => g.Description.SplitCamelCase()) .ToSeparatedString(", "); var otherGuardsDescritpion = otherGuards.Any() ? $" and {otherGuardsSummary}" : ""; return(stateConfig .PermitIf(trigger, destinationState, aggregateGuardExpression, $"{actorGuard.Description}{otherGuardsDescritpion}")); }
/// <summary> /// Permits for. /// </summary> /// <param name="allowedActors">The allowed actors.</param> /// <returns></returns> protected TransitionGuard For(params TActor[] allowedActors) { var actorGuard = new TransitionGuard( guardMethod: () => _actorProvider .GetCurrentImpersonations() .Any(allowedActors.Contains), description: allowedActors .Select(r => r.ToString()) .ToSeparatedString(", ") ); return (actorGuard); }