/// <summary>
        /// Adds a composite event to the state machine. A composite event is triggered when all
        /// off the required events have been raised. Note that required events cannot be in the initial
        /// state since it would cause extra instances of the state machine to be created
        /// </summary>
        /// <param name="propertyExpression">The composite event</param>
        /// <param name="trackingPropertyExpression">The property in the instance used to track the state of the composite event</param>
        /// <param name="events">The events that must be raised before the composite event is raised</param>
        protected void Event(Expression <Func <Event> > propertyExpression,
                             Expression <Func <TInstance, CompositeEventStatus> > trackingPropertyExpression,
                             params Event[] events)
        {
            if (events == null)
            {
                throw new ArgumentNullException("events");
            }
            if (events.Length > 31)
            {
                throw new ArgumentException("No more than 31 events can be combined into a single event");
            }
            if (events.Length == 0)
            {
                throw new ArgumentException("At least one event must be specified for a composite event");
            }
            if (events.Any(x => x == null))
            {
                throw new ArgumentException("One or more events specified has not yet been initialized");
            }

            PropertyInfo eventProperty        = propertyExpression.GetPropertyInfo();
            PropertyInfo trackingPropertyInfo = trackingPropertyExpression.GetPropertyInfo();

            string name = eventProperty.Name;

            var @event = new SimpleEvent(name);

            eventProperty.SetValue(this, @event);

            _eventCache[name] = new StateMachineEvent <TInstance>(@event);

            var complete = new CompositeEventStatus(Enumerable.Range(0, events.Length)
                                                    .Aggregate(0, (current, x) => current | (1 << x)));

            for (int i = 0; i < events.Length; i++)
            {
                int flag = 1 << i;

                var activity = new CompositeEventActivity <TInstance>(trackingPropertyInfo, flag, complete,
                                                                      (consumer, instance) => ((StateMachine <TInstance>) this).RaiseEvent(consumer, instance, @event));

                foreach (var state in _stateCache.Where(x => !Equals(x, Initial)))
                {
                    During(state,
                           When(events[i])
                           .Then(() => activity));
                }
            }
        }
Пример #2
0
        void CompositeEvent(Expression <Func <Event> > propertyExpression, CompositeEventStatusAccessor <TInstance> accessor,
                            CompositeEventOptions options, Event[] events)
        {
            if (events == null)
            {
                throw new ArgumentNullException(nameof(events));
            }
            if (events.Length > 31)
            {
                throw new ArgumentException("No more than 31 events can be combined into a single event");
            }
            if (events.Length == 0)
            {
                throw new ArgumentException("At least one event must be specified for a composite event");
            }
            if (events.Any(x => x == null))
            {
                throw new ArgumentException("One or more events specified has not yet been initialized");
            }

            PropertyInfo eventProperty = propertyExpression.GetPropertyInfo();

            string name = eventProperty.Name;

            var @event = new TriggerEvent(name);

            eventProperty.SetValue(this, @event);

            _eventCache[name] = new StateMachineEvent <TInstance>(@event, false);

            var complete = new CompositeEventStatus(Enumerable.Range(0, events.Length)
                                                    .Aggregate(0, (current, x) => current | (1 << x)));

            for (int i = 0; i < events.Length; i++)
            {
                int flag = 1 << i;

                var activity = new CompositeEventActivity <TInstance>(accessor, flag, complete, @event);

                Func <State <TInstance>, bool> filter = x => options.HasFlag(CompositeEventOptions.IncludeInitial) || !Equals(x, Initial);
                foreach (var state in _stateCache.Values.Where(filter))
                {
                    During(state,
                           When(events[i])
                           .Execute(x => activity));
                }
            }
        }