private void OnJumpToState(object sender, JumpToStateCallback e) { SequenceNumberOfCurrentState = e.payload.actionId; using (Store.BeginInternalMiddlewareChange()) { Dictionary <string, IFeature> featuresByName = Store.Features.ToDictionary(x => x.GetName()); var newFeatureStates = (IDictionary <string, object>)JsonUtil.Deserialize <object>(e.state); foreach (KeyValuePair <string, object> newFeatureState in newFeatureStates) { // Get the feature with the given name if (!featuresByName.TryGetValue(newFeatureState.Key, out IFeature feature)) { continue; } // Get the generic method of JsonUtil.Deserialize<> so we have the correct object type for the state string deserializeMethodName = nameof(JsonUtil.Deserialize); MethodInfo deserializeMethodInfo = typeof(JsonUtil) .GetMethod(deserializeMethodName) .GetGenericMethodDefinition() .MakeGenericMethod(new Type[] { feature.GetStateType() }); // Get the state we were given as a json string string serializedFeatureState = newFeatureState.Value?.ToString(); // Deserialize that json using the generic method, so we get an object of the correct type object stronglyTypedFeatureState = string.IsNullOrEmpty(serializedFeatureState) ? null : deserializeMethodInfo.Invoke(null, new object[] { serializedFeatureState }); // Now set the feature's state to the deserialized object feature.RestoreState(stronglyTypedFeatureState); } } FluxorComponent.AllStateHasChanged(); }
public async Task DispatchAsync(IAction action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } // Do not allow task dispatching inside a middleware-change. // These change cycles are for things like "jump to state" in Redux Dev Tools // and should be short lived. // We avoid dispatching inside a middleware change because we don't want UI events (like component Init) // that trigger actions (such as fetching data from a server) to execute if (IsInsideMiddlewareChange) { return; } if (!HasActivatedStore) { throw new InvalidOperationException("Store has not been initialized. Add `@Store.Initialize()` to your layout page"); } var actionsToDispatch = new Queue <IAction>(); actionsToDispatch.Enqueue(action); while (actionsToDispatch.Any()) { IAction currentActionToDispatch = actionsToDispatch.Dequeue(); // Allow middlewares to veto the dispatching of an action if (Middlewares.Any(x => !x.MayDispatchAction(currentActionToDispatch))) { break; } ExecuteMiddlewareBeforeDispatch(currentActionToDispatch); // Notify all features of this action foreach (var featureInstance in FeaturesByName.Values) { NotifyFeatureOfDispatch(featureInstance, currentActionToDispatch); } ; FluxorComponent.AllStateHasChanged(); IEnumerable <IAction> actionsCreatedByMiddlewares = ExecuteMiddlewareAfterDispatch(currentActionToDispatch) ?? new IAction[0]; // Get any actions generated by side-effects IEnumerable <IAction> actionsCreatedBySideEffects = await TriggerEffects(currentActionToDispatch); // Now execute any new actions IEnumerable <IAction> allNewActionsToDispatch = actionsCreatedByMiddlewares.Union(actionsCreatedBySideEffects); foreach (IAction newActionToDispatch in allNewActionsToDispatch) { actionsToDispatch.Enqueue(newActionToDispatch); } } }