Example #1
0
        private IEnumerable <string> GetPathArray <TSlice>(IStoreAction <TState, TSlice> action) where TSlice : class, new()
        {
            var expression = action.GetActionPath();
            var pathArray  = expression.Body.ToString().Split('.').Skip(1);

            return(pathArray);
        }
Example #2
0
 private void EnsureValidAction <TSlice>(IStoreAction <TState, TSlice> action) where TSlice : class, new()
 {
     if (action == null)
     {
         throw new ArgumentException($"Action can not be null");
     }
 }
Example #3
0
        private string GetPath <TSlice>(IStoreAction <TState, TSlice> action) where TSlice : class, new()
        {
            IEnumerable <string> pathArray = GetPathArray(action);
            var path = string.Join(".", pathArray);

            return(path);
        }
Example #4
0
        /// <summary>
        /// Subscribe to a specifc slice of the global state
        /// </summary>
        /// <typeparam name="TSlice">The type of the slice</typeparam>
        /// <param name="action">The action responsible for the slice</param>
        /// <param name="callback">The callback perfomerd when the slice is changed</param>
        public IStorageSubscription Subscribe <TSlice>(IStoreAction <TState, TSlice> action, Action <TSlice> callback) where TSlice : class, new()
        {
            EnsureValidAction(action);

            var actionPath = this.GetPath(action);

            if (string.IsNullOrWhiteSpace(actionPath))
            {
                maincallbacks.Add(callback);
                return(new StorageSubscription(maincallbacks, callback));
            }

            if (callbacks.ContainsKey(actionPath))
            {
                var list = callbacks[actionPath];
                list.Add(callback);
                return(new StorageSubscription(list, callback));
            }
            else
            {
                var list = new List <Delegate>();
                list.Add(callback);
                callbacks.Add(actionPath, list);
                return(new StorageSubscription(list, callback));
            }
        }
Example #5
0
        /// <summary>
        /// Selects a specific slice of the global state
        /// </summary>
        /// <typeparam name="TSlice">The type of the slice</typeparam>
        /// <param name="action">The action responsible for the slice</param>
        /// <returns></returns>
        public TSlice Select <TSlice>(IStoreAction <TState, TSlice> action) where TSlice : class, new()
        {
            EnsureValidAction(action);

            // Gets the Object that will be changed
            object currentObject = GetStoreObjectByPath(this.state, action);

            return(this.mapper.Clone <TSlice>(currentObject));
        }
Example #6
0
        /// <summary>
        /// Sets a specific slice of the global state
        /// </summary>
        /// <typeparam name="TSlice">The type of the slice that will be changed</typeparam>
        /// <param name="action">The action responsible for the slice</param>
        /// <param name="slice">The new state to be dispatched</param>
        public void SetState <TSlice>(IStoreAction <TState, TSlice> action, TSlice slice) where TSlice : class, new()
        {
            // Ensures that the action is valid
            EnsureValidAction(action);

            var actionPath = this.GetPath(action);
            var actionName = action?.GetActionName();

            // Copies the new state of the store
            var newState = this.mapper.Clone(this.state);

            // Gets the Object that will be changed
            object newSlice = GetStoreObjectByPath(newState, action);

            // Maps the new state to the object that will be changed
            mapper.Map(slice, newSlice);

            // Adds the state history
            var stateEntry = new StateEntry <TState>
            {
                ActionPath = actionPath,
                ActionName = actionName,
                OldState   = this.state,
                NewState   = newState,
                UpdatedAt  = DateTimeOffset.Now
            };

            stateHistory.Add(stateEntry);

            // Changes the store to the new state
            this.state = newState;

            // Notifies the main subscribers
            foreach (var callback in maincallbacks)
            {
                callback.DynamicInvoke(this.state);
            }

            // Notifies the subscribers to child states
            if (actionPath != null && callbacks.ContainsKey(actionPath))
            {
                foreach (var callback in callbacks[actionPath])
                {
                    callback.DynamicInvoke(newSlice);
                }
            }

            // Logs the history
            if (isLogEnabled)
            {
                logging.Log($"*** State changed on {typeof(TState).Name} ***");
                logging.Log(jsonService.Serialize(stateEntry));
            }

            // Notifies that the state was changed
            //this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.State)));
        }
Example #7
0
        private object GetStoreObjectByPath <TSlice>(TState newState, IStoreAction <TState, TSlice> action) where TSlice : class, new()
        {
            object currentObject = newState;
            var    pathArray     = this.GetPathArray(action);

            foreach (var pathItem in pathArray)
            {
                var prop      = currentObject.GetType().GetProperty(pathItem);
                var newObject = prop.GetValue(currentObject);

                if (newObject == null)
                {
                    newObject = Activator.CreateInstance(prop.PropertyType);
                    prop.SetValue(currentObject, newObject);
                }

                currentObject = newObject;
            }

            return(currentObject);
        }