コード例 #1
0
        public MobTransitionResult Go(IEvent @event, Tuple <TEntity1, TEntity2> mob)
        {
            if (Stators.Count != 2)
            {
                throw StatorConfigurationException.MobEntitiesAndStateMachinesCountNotEquals(2, Stators.Count);
            }

            var rollbackActions   = new List <Action>();
            var transitionActions = new List <Func <Tuple <Type, bool, FailureTypes> > >();

            PrepareDelegates(mob.Item1, @event, rollbackActions, transitionActions);
            PrepareDelegates(mob.Item2, @event, rollbackActions, transitionActions);

            try
            {
                return(ProcessResult(transitionActions.Select(x => x?.Invoke()).ToArray()));
            }
            catch
            {
                if (_withRollbackOnFailure)
                {
                    rollbackActions.ForEach(x => x?.Invoke());
                }
                throw;
            }
        }
コード例 #2
0
        private void BuildMap(object[] mobEntity)
        {
            var count = mobEntity.Length;

            _typePreparersMap = new Dictionary <Type, Action <object, IEvent, List <Action>, List <Func <Tuple <Type, bool, FailureTypes> > > > >();
            var touchedEntities = new Type[count];

            for (var i = 0; i < count; i++)
            {
                var entity     = mobEntity[i];
                var entityType = entity.GetType();
                if (Array.IndexOf(touchedEntities, entityType) >= 0)
                {
                    throw StatorConfigurationException.MobStatorCantPropessDuplicatedEntities(entityType);
                }

                touchedEntities[i] = entityType;

                var constThis = Expression.Constant(this);
                var inEntityParam = Expression.Parameter(typeof(object), "entity");
                var entityParam = Expression.Convert(inEntityParam, entityType); var eventParam = Expression.Parameter(typeof(IEvent), "@event");
                var rollbackActionsParam    = Expression.Parameter(typeof(List <Action>), "rollbackActions");
                var transitionInvokersParam = Expression.Parameter(typeof(List <Func <Tuple <Type, bool, FailureTypes> > >), "transitionInvokers");


                var callExp = Expression.Call(constThis, nameof(PrepareDelegates), new Type[] { entityType }, new Expression[] { entityParam, eventParam, rollbackActionsParam, transitionInvokersParam });

                var lambda   = Expression.Lambda(callExp, new[] { inEntityParam, eventParam, rollbackActionsParam, transitionInvokersParam });
                var compiled = (Action <object, IEvent, List <Action>, List <Func <Tuple <Type, bool, FailureTypes> > > >)lambda.Compile();

                _typePreparersMap.Add(entityType, compiled);
            }
        }
コード例 #3
0
        public MobTransitionResult Go(IEvent @event, params object[] mob)
        {
            if (_typePreparersMap == null)
            {
                BuildMap(mob);
            }

            var entitiesCount = mob.Length;

            if (Stators.Count != entitiesCount)
            {
                throw StatorConfigurationException.MobEntitiesAndStateMachinesCountNotEquals(entitiesCount, Stators.Count);
            }

            var rollbackActions   = new List <Action>();
            var transitionActions = new List <Func <Tuple <Type, bool, FailureTypes> > >();

            foreach (var item in mob)
            {
                _typePreparersMap[item.GetType()](item, @event, rollbackActions, transitionActions);
            }

            try
            {
                return(ProcessResult(transitionActions.Select(x => x?.Invoke()).ToArray()));
            }
            catch
            {
                if (_withRollbackOnFailure)
                {
                    rollbackActions.ForEach(x => x?.Invoke());
                }
                throw;
            }
        }
コード例 #4
0
        internal void AddStatorNode <TEntity, TEntityState>(IStator <TEntity, TEntityState> stator) where TEntity : class
        {
            var nodeType = typeof(TEntity);

            if (Stators.Keys.Contains(nodeType))
            {
                throw StatorConfigurationException.MobStatorCantSetForDuplicatedEntities(nodeType);
            }
            var accessor = new EntityGetSetAccessor
            {
                TransitionInvoker = (entity, @event) => stator.Go((TEntity)entity, (IEvent)@event),
                GetInvoker        = (entity) => stator.GetGetter()((TEntity)entity),
                SetInvoker        = (entity, state) => stator.GetSetter()((TEntity)entity, (TEntityState)state)
            };

            Stators[nodeType] = accessor;
        }
コード例 #5
0
        protected void PrepareDelegates <T>(T entity, IEvent @event, List <Action> rollbackActions, List <Func <Tuple <Type, bool, FailureTypes> > > transitionActions) where T : class
        {
            var type = typeof(T);

            if (!Stators.TryGetValue(type, out var entityAccessor) || entityAccessor == null)
            {
                throw StatorConfigurationException.MobEntityStateMachineNotRegistered(type);
            }

            var    transitionInvoker = entityAccessor.TransitionInvoker;
            var    setInvoker        = entityAccessor.SetInvoker;
            var    getInvoker        = entityAccessor.GetInvoker;
            var    oldValue          = getInvoker(entity);
            Action rollbackAction    = () => setInvoker(entity, oldValue);

            rollbackActions.Add(rollbackAction);
            transitionActions.Add(() =>
            {
                var result = (TransitionResult <T>)transitionInvoker(entity, @event);
                return(Tuple.Create(type, result.Success, result.FailureType));
            });
        }