コード例 #1
0
ファイル: StateMachine.cs プロジェクト: OkunevPY/corewf
        /// <summary>
        /// Create internal states
        /// </summary>
        /// <param name="metadata">NativeActivityMetadata reference.</param>
        private void ProcessStates(NativeActivityMetadata metadata)
        {
            // remove duplicate state in the collection during evaluation
            IEnumerable <State> distinctStates = _states.Distinct();

            foreach (State state in distinctStates)
            {
                InternalState internalState = state.InternalState;
                _internalStates.Add(internalState);

                DelegateInArgument <StateMachineEventManager> eventManager = new DelegateInArgument <Statements.StateMachineEventManager>();
                internalState.EventManager = eventManager;

                ActivityFunc <StateMachineEventManager, string> activityFunc = new ActivityFunc <StateMachineEventManager, string>
                {
                    Argument = eventManager,
                    Handler  = internalState,
                };

                if (state.Reachable)
                {
                    // If this state is not reached, we should not add it as child because it's even not well validated.
                    metadata.AddDelegate(activityFunc, /* origin = */ state);
                }

                _internalStateFuncs.Add(activityFunc);
            }
        }
コード例 #2
0
 /// <summary>
 /// Clear internal state.
 /// </summary>
 internal void ClearInternalState()
 {
     this.internalState = null;
 }
コード例 #3
0
 /// <summary>
 /// Clear internal state.
 /// </summary>
 internal void ClearInternalState()
 {
     _internalState = null;
 }
コード例 #4
0
        protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
        {
            InternalState originalInternalState = (InternalState)originalActivity;

            // NOTE: State.Entry/Exit are allowed to be removed, because it doesn't change the execution semantics of SM
            // if this removed activity was executing, WF runtime would disallow the update.
            Activity entryActivityMatch = metadata.GetMatch(this.Entry);
            Activity exitActivityMatch  = metadata.GetMatch(this.Exit);

            if ((null != entryActivityMatch && !object.ReferenceEquals(entryActivityMatch, originalInternalState.Entry)) ||
                (null != exitActivityMatch && !object.ReferenceEquals(exitActivityMatch, originalInternalState.Exit)))
            {
                // original State.Entry/Exit is replaced with another child activities with InternalState
                // new State.Entry/Exit is moved from another child activities within InternalState.
                metadata.DisallowUpdateInsideThisActivity(SR.MovingActivitiesInStateBlockDU);
                return;
            }

            int originalTriggerInUpdatedDefinition = 0;

            foreach (InternalTransition originalTransition in originalInternalState.internalTransitions)
            {
                if (metadata.IsReferenceToImportedChild(originalTransition.Trigger))
                {
                    metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
                    return;
                }

                if (!originalTransition.IsUnconditional)
                {
                    // new Trigger activity
                    foreach (TransitionData transitionData in originalTransition.TransitionDataList)
                    {
                        if (metadata.IsReferenceToImportedChild(transitionData.Condition))
                        {
                            metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
                            return;
                        }
                    }
                }
            }

            foreach (InternalTransition updatedTransition in this.internalTransitions)
            {
                if (metadata.IsReferenceToImportedChild(updatedTransition.Trigger))
                {
                    // if the trigger is referenced, it might have another save values already.
                    metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
                    return;
                }

                Activity triggerMatch = metadata.GetMatch(updatedTransition.Trigger);

                if (null != triggerMatch)
                {
                    InternalTransition originalTransition;

                    if (originalInternalState.triggerInternalTransitionMapping.TryGetValue(triggerMatch, out originalTransition))
                    {
                        originalTriggerInUpdatedDefinition++;

                        if (originalTransition.IsUnconditional)
                        {
                            string errorMessage;
                            bool   canTransitionBeUpdated = ValidateDUInUnconditionalTransition(metadata, updatedTransition, originalTransition, out errorMessage);

                            if (!canTransitionBeUpdated)
                            {
                                metadata.DisallowUpdateInsideThisActivity(errorMessage);
                                return;
                            }
                        }
                        else
                        {
                            if (updatedTransition.IsUnconditional)
                            {
                                // cannot change the transition from condition to unconditional.
                                metadata.DisallowUpdateInsideThisActivity(SR.ChangeConditionalTransitionToUnconditionalBlockDU);
                                return;
                            }
                            else
                            {
                                string errorMessage;
                                bool   canTransitionBeUpdated = ValidateDUInConditionTransition(metadata, updatedTransition, originalTransition, out errorMessage);

                                if (!canTransitionBeUpdated)
                                {
                                    metadata.DisallowUpdateInsideThisActivity(errorMessage);
                                    return;
                                }
                            }
                        }
                    }
                    else
                    {
                        // the trigger is an child activity moved from elsewhere within the state
                        metadata.DisallowUpdateInsideThisActivity(SR.MovingActivitiesInStateBlockDU);
                        return;
                    }
                }
                else
                {
                    // new Trigger activity
                    foreach (TransitionData transitionData in updatedTransition.TransitionDataList)
                    {
                        if ((null != transitionData.Condition && null != metadata.GetMatch(transitionData.Condition)) ||
                            (null != transitionData.Action && null != metadata.GetMatch(transitionData.Action)))
                        {
                            // if a new transition is added, it is expected that the Condition/Action
                            // are newly created.
                            metadata.DisallowUpdateInsideThisActivity(SR.ChangingTriggerOrUseOriginalConditionActionBlockDU);
                            return;
                        }
                    }
                }
            }

            if (originalTriggerInUpdatedDefinition != originalInternalState.internalTransitions.Count)
            {
                // NOTE: in general, if the transition is removed when there are pending triggers,
                // runtime would be able to detect the missing child activities.  However, in cases,
                // where the transition is happening already (in between completion of Transition.Action
                // callback but before InternalState is completed), the workflow definition can be unloaded
                // and updated.  The InternalState is unable to trace the original transition that set the
                // destination state index.  In that case, the update would fail at UpdateInstance.
                // To simplify the model, it is more convenient to disallow removing existing transitions
                // from an executing InternalState.  The only extra restriction it brings, is that it disables
                // update even if the InternalState is uploaded at State.Entry.  This scenario, however, is uncommon.
                metadata.DisallowUpdateInsideThisActivity(SR.RemovingTransitionsBlockDU);
            }
        }