internal EntitySelectors( IComparer <TEntity> sortComparer ) { SelectIds = CreateSelector( (EntityState <TEntity, TKey> entityState) => entityState.Ids ); SelectCollection = CreateSelector( (EntityState <TEntity, TKey> entityState) => entityState.Collection ); SelectEntities = CreateSelector( SelectCollection, collection => { var result = collection .Select(x => x.Value) .ToList(); if (sortComparer != null) { result.Sort(sortComparer); } return(result); } ); SelectCount = CreateSelector( SelectCollection, collection => collection.Count ); }
public MemoizedSelector( ISelectorWithoutProps <TInput, TSelectorResult> selector, Func <TSelectorResult, TOutput> projectorFunction ) { Selector = selector; ProjectorFunction = projectorFunction; }
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 new selector based on the previous ones. /// </summary> /// <typeparam name="TState">State to consume.</typeparam> /// <typeparam name="TSelectorResult1">Result of the previous selector.</typeparam> /// <typeparam name="TFinalResult">Result of the final selector.</typeparam> /// <param name="selector1">First selector.</param> /// <param name="projectorFunction">Selector that combines all values from the previous selectors.</param> /// <returns>A new selector using the previous ones.</returns> public static ISelectorWithoutProps <TState, TFinalResult> CreateSelector <TState, TSelectorResult1, TFinalResult>( ISelectorWithoutProps <TState, TSelectorResult1> selector1, Func <TSelectorResult1, TFinalResult> projectorFunction ) { return(new MemoizedSelector <TState, TSelectorResult1, TFinalResult>( selector1, projectorFunction )); }
/// <summary> /// Combine multiple selectors. /// </summary> /// <typeparam name="TState">Type of the root state.</typeparam> /// <typeparam name="TSelectorResult1">Type of the result of the first selector.</typeparam> /// <typeparam name="TSelectorResult2">Type of the result of the second selector.</typeparam> /// <param name="selector1">First selector.</param> /// <param name="selector2">Second selector.</param> /// <returns></returns> public static ISelectorWithoutProps <TState, Tuple <TSelectorResult1, TSelectorResult2> > CombineSelectors <TState, TSelectorResult1, TSelectorResult2>( ISelectorWithoutProps <TState, TSelectorResult1> selector1, ISelectorWithoutProps <TState, TSelectorResult2> selector2 ) { return(new MemoizedSelector <TState, TSelectorResult1, TSelectorResult2, Tuple <TSelectorResult1, TSelectorResult2> >( selector1, selector2, (result1, result2) => Tuple.Create(result1, result2) )); }
/// <summary> /// Creates an explicit state lens used for nested state reducers. /// </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">Selector to access the feature state from state.</param> /// <param name="stateReducer">The reducer function to update the nested <typeparamref name="TFeatureState"/> in the <typeparamref name="TState"/>.</param> /// <returns>An explicit state lens.</returns> public static IStateLens <TState, TFeatureState> CreateSubReducers <TState, TFeatureState>( ISelectorWithoutProps <TState, TFeatureState> featureSelector, Func <TState, TFeatureState, TState> stateReducer ) where TState : class, new() where TFeatureState : class, new() { var selector = new Func <TState, TFeatureState>(state => featureSelector.Apply(state)); return(new ExplicitStateLens <TState, TFeatureState>(selector, stateReducer)); }
/// <summary> /// Combine multiple selectors. /// </summary> /// <typeparam name="TState">Type of the root state.</typeparam> /// <typeparam name="TSelectorResult1">Type of the result of the first selector.</typeparam> /// <typeparam name="TSelectorResult2">Type of the result of the second selector.</typeparam> /// <typeparam name="TSelectorResult3">Type of the result of the third selector.</typeparam> /// <typeparam name="TSelectorResult4">Type of the result of the fourth selector.</typeparam> /// <param name="selector1">First selector.</param> /// <param name="selector2">Second selector.</param> /// <param name="selector3">Third selector.</param> /// <param name="selector4">Fourth selector.</param> /// <returns></returns> public static ISelectorWithoutProps <TState, Tuple <TSelectorResult1, TSelectorResult2, TSelectorResult3, TSelectorResult4> > CombineSelectors <TState, TSelectorResult1, TSelectorResult2, TSelectorResult3, TSelectorResult4>( ISelectorWithoutProps <TState, TSelectorResult1> selector1, ISelectorWithoutProps <TState, TSelectorResult2> selector2, ISelectorWithoutProps <TState, TSelectorResult3> selector3, ISelectorWithoutProps <TState, TSelectorResult4> selector4 ) { return(new MemoizedSelector <TState, TSelectorResult1, TSelectorResult2, TSelectorResult3, TSelectorResult4, Tuple <TSelectorResult1, TSelectorResult2, TSelectorResult3, TSelectorResult4> >( selector1, selector2, selector3, selector4, (result1, result2, result3, result4) => Tuple.Create(result1, result2, result3, result4) )); }
/// <summary> /// Create a new selector based on the previous ones. /// </summary> /// <typeparam name="TState">State to consume.</typeparam> /// <typeparam name="TSelectorResult1">Result of the first previous selector.</typeparam> /// <typeparam name="TSelectorResult2">Result of the second previous selector.</typeparam> /// <typeparam name="TSelectorResult3">Result of the third previous selector.</typeparam> /// <typeparam name="TSelectorResult4">Result of the fourth previous selector.</typeparam> /// <typeparam name="TFinalResult">Result of the final selector.</typeparam> /// <param name="selector1">First selector.</param> /// <param name="selector2">Second selector.</param> /// <param name="selector3">Third selector.</param> /// <param name="selector4">Fourth selector.</param> /// <param name="projectorFunction">Selector that combines all values from the previous selectors.</param> /// <returns>A new selector using the previous ones.</returns> public static ISelectorWithoutProps <TState, TFinalResult> CreateSelector <TState, TSelectorResult1, TSelectorResult2, TSelectorResult3, TSelectorResult4, TFinalResult>( ISelectorWithoutProps <TState, TSelectorResult1> selector1, ISelectorWithoutProps <TState, TSelectorResult2> selector2, ISelectorWithoutProps <TState, TSelectorResult3> selector3, ISelectorWithoutProps <TState, TSelectorResult4> selector4, Func <TSelectorResult1, TSelectorResult2, TSelectorResult3, TSelectorResult4, TFinalResult> projectorFunction ) { return(new MemoizedSelector <TState, TSelectorResult1, TSelectorResult2, TSelectorResult3, TSelectorResult4, TFinalResult>( selector1, selector2, selector3, selector4, projectorFunction )); }
/// <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)); }
/// <summary> /// Get selectors for the specified <see cref="EntityState{TEntity, TKey}"/>. /// </summary> /// <typeparam name="TInput">Part of the state used to create selectors.</typeparam> /// <param name="selectEntityState">Function used to select <see cref="EntityState{TEntity, TKey}"/> from the <typeparamref name="TInput"/>.</param> /// <returns>A new Entity Selectors.</returns> public EntitySelectors <TInput, TEntity, TKey> GetSelectors <TInput>( ISelectorWithoutProps <TInput, EntityState <TEntity, TKey> > selectEntityState ) { return(new EntitySelectors <TInput, TEntity, TKey>(selectEntityState, SortComparer)); }
public IObservable <TResult> Select <TResult>(ISelectorWithoutProps <TState, TResult> selector, string?optionsStr = null) { SelectInvoked = true; return(selector.Apply(_stateSubject)); }