/// <summary> /// Creates an implicit state lens used for nested state reducers. /// If possible, try to create an explicit state lens using <see cref="CreateSubReducers"/> function overrides. /// </summary> /// <typeparam name="TState">Type of the state to update.</typeparam> /// <typeparam name="TFeatureState">Type of the feature state which will be the target of reducers.</typeparam> /// <param name="featureSelector"></param> /// <returns>An implicit state lens.</returns> public static IStateLens <TState, TFeatureState> CreateSubReducers <TState, TFeatureState>(ISelectorWithoutProps <TState, TFeatureState> featureSelector) where TState : class, new() where TFeatureState : class, new() { var selector = new Func <TState, TFeatureState>(state => featureSelector.Apply(state)); return(new ImplicitStateLens <TState, TFeatureState>(selector)); }
public static On <TState>[] CreateSubReducers <TState, TFeatureState>( On <TFeatureState>[] featureReducers, ISelectorWithoutProps <TState, TFeatureState?> selectFeature ) where TState : class, new() where TFeatureState : class, new() { var parentStateProperties = typeof(TState).GetProperties(); return(featureReducers .Select(r => { return new On <TState> { Reduce = (state, action) => { if (r?.Reduce == null) { return state; } var featureState = selectFeature.Apply(state); if (featureState == null) { return state; } var reducerResult = r.Reduce(featureState, action); if (featureState.IsDeepEqual(reducerResult)) { return state; } var featureProperty = parentStateProperties .SingleOrDefault(p => { return p.GetValue(state) == featureState; }); if (featureProperty == null) { throw new NotSupportedException( $"A sub-reducer cannot find the feature reducer of `{typeof(TFeatureState).Name}` inside `{typeof(TState).Name}`." ); } var stateCopy = state.Copy(); featureProperty.SetValue(stateCopy, reducerResult); return stateCopy; }, Types = r.Types }; }) .ToArray()); }
/// <summary> /// Create a sub-reducers, for features-like purpose. /// </summary> /// <typeparam name="TState">Type of the root state.</typeparam> /// <typeparam name="TFeatureState">Type of the feature state.</typeparam> /// <param name="featureReducers">Reducers that directly use the feature state.</param> /// <param name="selectFeature">Select the feature from the root state.</param> /// <returns>Returns reducers targeting the root state.</returns> public static On <TState>[] CreateSubReducers <TState, TFeatureState>( On <TFeatureState>[] featureReducers, ISelectorWithoutProps <TState, TFeatureState> selectFeature ) where TState : class, new() where TFeatureState : class, new() { var selectFeatureType = selectFeature.GetType(); var selectFeatureInputType = selectFeatureType.GenericTypeArguments[0]; var selectFeatureOutputType = selectFeatureType.GenericTypeArguments[1]; var featureProperty = selectFeatureInputType.GetProperties() .Single(p => p.PropertyType.FullName == selectFeatureOutputType.FullName); return(featureReducers .Select(r => { return new On <TState> { Reduce = (state, action) => { var featureState = selectFeature.Apply(state); var reducerResult = r.Reduce(featureState, action); if (IsDeepEqual(featureState, reducerResult)) { return state; } var stateCopy = state.Copy(); featureProperty.SetValue(stateCopy, reducerResult); return stateCopy; }, Types = r.Types }; }) .ToArray()); }
/// <summary> /// Select a value derived from the state of the store. /// </summary> /// <typeparam name="TResult">The type of the selector result.</typeparam> /// <param name="selector"> /// The mapping function that can be applied to get the desired partial state of type <typeparamref name="TResult"/> from an instance of <typeparamref name="TState"/>. /// </param> /// <returns></returns> public IObservable <TResult> Select <TResult>(ISelectorWithoutProps <TState, TResult> selector) { return(selector.Apply(_stateSubject)); }
public IObservable <TResult> Select <TResult>(ISelectorWithoutProps <TState, TResult> selector, string?optionsStr = null) { SelectInvoked = true; return(selector.Apply(_stateSubject)); }