interface Urunium.Redux.IReducer<TState>
Reducer takes in a state, applies an action and returns resultant state. Action can be any object that is supported by reducer, there isn't any hard and fast rule for action. Could even be primitive types.
Examples
class IncrementAction { }
class DecrementAction { }
class Counter : IReducer<int>
{
public int Apply(int previousState, object action)
{
switch (action)
{
case IncrementAction inc:
return previousState + 1;
case DecrementAction dec:
return previousState - 1;
}
// Unsupported actions should return previousState unchanged.
return previousState;
}
}
Methods
-
TState Apply (TState previousState, Object action)
Apply an action to old state and return a new state.Returns: New state
Parameters:
-
TState previousState
Existing state -
Object action
Action that needs to be applied
-
interface Urunium.Redux.IStore<TState>
Store is responsible for holding state. Dispatch action to reducer, and notify about change in state to subscribers. Default implementation for this interface is Urunium.Redux.Store<TState> .
Methods
-
void Dispatch <TAction>(TAction action)
Dispatch action to reducers which will then apply the actions. Also, notifies about state change by firing StageChanged event.Parameters:
- TAction action
Instance ofAction
that needs to be applied to current state of Store. Applying an action may transform a state into new state.
- TAction action
Events
- EventHandler<EventArgs> StateChanged
Can be subscribed to get notified about change in state.
Properties and Fields
- TState State
Application's State object which needs to be held by this store.
class Urunium.Redux.Store<TState>
Default implementation of Urunium.Redux.IStore<TState> . A store is generally a singleton global object that holds entire state of the application. Store can be used to route actions to reducers, to change the current state to new desired state using Dispatch<TAction>(TAction action) method, the change in state can be listened through StateChanged event, and the current state can be accessed through State property. Note that only way to modify state is through dispatching an action through store.
Examples
class IncrementAction { }
class DecrementAction { }
class Counter : IReducer<int>
{
public int Apply(int previousState, object action)
{
switch (action)
{
case IncrementAction inc:
return previousState + 1;
case DecrementAction dec:
return previousState - 1;
}
// Unsupported actions should return previousState unchanged.
return previousState;
}
}
// Using Reducer in store.
var rootReducer = new Counter();
var initialState = 0;
var store = new Store<int>(rootReducer, initialState);
store.StateChanged += (sender, eventArgs) =>
{
// update ui
Console.WriteLine(store.State);
};
store.Dispatch(new IncrementAction());
// 1
store.Dispatch(new IncrementAction());
// 2
store.Dispatch(new DecrementAction());
// 1
Constructors
-
Urunium.Redux.Store<TState> (Urunium.Redux.IReducer<TState> rootReducer, TState initialState)
Store should take in the root reducer, and initial state.Parameters:
-
IReducer<TState> rootReducer
The root reducer is responsible for distributing all the incomming actions to correct reducer. -
TState initialState
The initial state of application when store is constructed for first time.
-
Methods
-
void Dispatch <TAction>(TAction action)
Dispatch action to reducers which will then apply the actions. Also, notifies about state change by firing StageChanged event.Parameters:
- TAction action
Instance ofAction
that needs to be applied to current state of Store. Applying an action may transform a state into new state.
- TAction action
Events
- EventHandler<EventArgs> StateChanged
Can be subscribed to get notified about change in state.
Properties and Fields
- TState State
Get application's State object which needs to be held by this store.
class Urunium.Redux.Undoable.Redo
Action to "Redo" state, as in (Undo/redo).
Constructors
class Urunium.Redux.Undoable.Undo
Action to "Undo" state, as in (Undo/redo).
Constructors
class Urunium.Redux.Undoable.UndoableState<TState>
Datastructure to support undo/redo for state. Use this in conjunction with Urunium.Redux.Undoable.UndoableReducer<TState> to support Urunium.Redux.Undoable.Undo / Urunium.Redux.Undoable.Redo actions. The store instance must be Urunium.Redux.IStore<TState> of Urunium.Redux.Undoable.UndoableState<TState> where TState is the type of application's state.
Constructors
-
Urunium.Redux.Undoable.UndoableState<TState> (TState present, System.Collections.Generic.IReadOnlyList<TState> past, System.Collections.Generic.IReadOnlyList<TState> future)
Create an instance of Urunium.Redux.Undoable.UndoableState<TState> , with current state, past states and future states.Parameters:
-
TState present
Current state. -
IReadOnlyList<TState> past
List of past states. -
IReadOnlyList<TState> future
List of future states.
-
-
Urunium.Redux.Undoable.UndoableState<TState> (TState present)
Create an instance of Urunium.Redux.Undoable.UndoableState<TState> , with just current state.Parameters:
- TState present
Properties and Fields
- IReadOnlyList<TState> Past
List of past states
- IReadOnlyList<TState> Future
List of future states
- TState Present
Current state.
class Urunium.Redux.Undoable.UndoableReducer<TState>
Reducer to support undo/redo. This reducer is an enhancer for actual Urunium.Redux.IReducer<TState> , which handles Urunium.Redux.Undoable.Undo / Urunium.Redux.Undoable.Redo actions and forwards all other action to underlying reducer. Use this in conjunction with Urunium.Redux.Undoable.UndoableState<TState> to support Urunium.Redux.Undoable.Undo / Urunium.Redux.Undoable.Redo actions.
Examples
// Root reducer.
public class Counter : Typed.TypedReducer<int>
{
public int Apply(int previousState, Increment action)
{
return previousState + 1;
}
public int Apply(int previousState, Decrement action)
{
return previousState - 1;
}
}
// usage of UndoableState and UndoableReducer...
IStore<UndoableState<int>> store = new Store<UndoableState<int>>(
new UndoableReducer<int>(new Counter()),
new UndoableState<int>(0));
Constructors
-
Urunium.Redux.Undoable.UndoableReducer<TState> (Urunium.Redux.IReducer<TState> innerReducer, [int keep])
Create an instance of Urunium.Redux.Undoable.UndoableReducer<TState> .Parameters:
-
IReducer<TState> innerReducer
Reducer which needs to be enhanced with undo/redo ability. -
int keep (optional, default: 10)
Number of historical states to be preserved while supporting undo/redo.
-
Methods
-
UndoableState<TState> Apply (Urunium.Redux.Undoable.UndoableState<TState> previousState, Object action)
Reducer function to support undo/redo.Returns: New state after applying action.
Parameters:
-
UndoableState<TState> previousState
Current state stored in Urunium.Redux.Store<TState> object. -
Object action
Action to be applied to state.
-
interface Urunium.Redux.Typed.IApply<TState, TAction>
Helper interface to be used with Urunium.Redux.Typed.TypedReducer<TState> . Note that Urunium.Redux.Typed.TypedReducer<TState> does work without implementing Urunium.Redux.Typed.IApply<TState, TAction> interface, but implementing this interface helps in making implementation more testable, and in visual studio it also helps in generating template methods.
Examples
public class Counter : Typed.TypedReducer<int>, IApply<int, Increment>, IApply<int, Decrement>;
{
public int Apply(int previousState, Increment action)
{
return previousState + 1;
}
public int Apply(int previousState, Decrement action)
{
return previousState - 1;
}
}
Methods
-
TState Apply (TState previousState, TAction action)
Reducer function that applies specific type of TAction to given TState.Returns: New state after applying action.
Parameters:
-
TState previousState
The state currently stored in Store -
TAction action
Action to be applied to state
-
class Urunium.Redux.Typed.TypedReducer<TState>
A Urunium.Redux.Typed.TypedReducer<TState> is essentially an Urunium.Redux.IReducer<TState> whose Apply method forwards call to other Apply methods with correct signature. The apply methods are strongly typed, hence provids ability to divide reducer functions by Action type.
Examples
// Root reducer.
public class Counter : Typed.TypedReducer<int>
{
public int Apply(int previousState, Increment action)
{
return previousState + 1;
}
public int Apply(int previousState, Decrement action)
{
return previousState - 1;
}
}
Constructors
- Urunium.Redux.Typed.TypedReducer<TState> ()
Instantiate new Urunium.Redux.Typed.TypedReducer<TState>
Methods
-
TState Apply (TState previousState, Object action)
Base Apply method from Urunium.Redux.IReducer<TState>Parameters:
-
TState previousState
-
Object action
-
class Urunium.Redux.Logic.AnyAction
Utility class for ability to handle any type of action. To be used in conjunction with Urunium.Redux.Logic.LogicBase<TState, TAction> class. To get the instance of action that was actually dispatched use ActualAction property.
Examples
interface IAction
{
long TimeStamp { get; set; }
}
// An implementation of logic that can handle any action.
class AddTimeStamp<AppState> : LogicBase<AppState, AnyAction>
{
public override Type CancelType => null; // Nothing can cancel this.
public override uint Priority => 0; // No priority. Bigger number gets higer priority.
protected override Task<AnyAction> OnTransfrom(Func<AppState> getState, AnyAction action, CancellationToken cancellationToken)
{
if (action.ActualAction is IAction actualAction)
{
actualAction.TimeStamp = DateTime.UtcNow.Ticks;
}
return base.OnTransfrom(getState, action, cancellationToken);
}
}
Properties and Fields
- Object ActualAction
Actual action that was dispatched.
interface Urunium.Redux.Logic.IPriority
Give priority to your Logic. In case two logic handles same action, but sequence in which these must be handled matters then set higher priority to logic that must be executed first.
Properties and Fields
- uint Priority
Priority of logic. Priority is calculated in descending order. i.e. Greater the number higher the priority
interface Urunium.Redux.Logic.ICancelable
Make logic cancelable.
Methods
-
void Cancel <TCancel>(TCancel cancelAction)
Request cancelingParameters:
- TCancel cancelAction
Properties and Fields
- Type CancelType
Type of action that when dispatched will cancel this process
interface Urunium.Redux.Logic.ILogic<TState, TAction>
Interface representing a Logic
. A class must implement this interface, if it wants to get registered in store as a logic.
Logic
here typically means "business logic", a validation, transformation or some kind of processing.
Methods
-
System.Threading.Tasks.Task<Urunium.Redux.Logic.PreProcessResult> PreProcess (Urunium.Redux.IStore<TState> store, TAction action)
Preprocess an action before it is dispatched to store. E.g. Validate action, Transform action etc. In case multiple logic handles same action type, then preprocess of each logic is executed in order of priority before dispatching action.Returns: An instance of Urunium.Redux.Logic.PreProcessResult , indicating whether or not next logic in chain should be executed. Note that, setting PreProcessResult.ContinueToNextStep to false will stop logic chaing right there. Even Process(System.Func<TState> getState, TAction action, Urunium.Redux.Logic.IMultiDispatcher dispatcher) is also not executed
Parameters:
-
IStore<TState> store
Store -
TAction action
Action that needs to be preprocessed.
-
-
System.Threading.Tasks.Task Process (System.Func<TState> getState, TAction action, Urunium.Redux.Logic.IMultiDispatcher dispatcher)
Processing of dispatched action. This gets executed after PreProcess(Urunium.Redux.IStore<TState> store, TAction action) and, Dispatch<TAction>(TAction action) . Typically pre-processing is to handle scenarios before dispatching action, and process is for handling after dispatching.Returns: async Task (instead of async void.)
Parameters:
-
Func<TState> getState
Function to get current state. -
TAction action
Action that needs to be processed. -
Urunium.Redux.Logic.IMultiDispatcher dispatcher
Multi dispatcher.
-
Properties and Fields
- bool IsLongRunning
Indicate that this is a long running process, so other logics must continue while this is running in background (i.e. don't wait for it to complete). Long running processes are given separate thread, through use of: System.Threading.Tasks.TaskCreationOptions.LongRunning . Implementor doesn't need to concern with running it in separate thread. Note: - PreProcess(Urunium.Redux.IStore<TState> store, TAction action) cannot be long running.
- Only Process(System.Func<TState> getState, TAction action, Urunium.Redux.Logic.IMultiDispatcher dispatcher) can be long running.
interface Urunium.Redux.Logic.ILogicConfiguration<TState>
Configuration helper for logic extension, to add logic to store.
Methods
-
void AddLogics <TAction>(Urunium.Redux.Logic.ILogic<TState, TAction>[] logics)
Add a business logic that will listen to particular action beign dispatched to store.Parameters:
- ILogic<TState, TAction>[] logics
Array of logics; processing particular action type. Multiple calls are needed to handle different action types.
- ILogic<TState, TAction>[] logics
interface Urunium.Redux.Logic.IMultiDispatcher
A scope under which Dispatch
doesn't immediately fire state changed event. State is
changed silently and one state changed event is fired when scope gets disposed.
Methods
-
void Dispatch <TAction>(TAction action)
Dispatch action to store, without firing StateChange event. All state changes are done silently, and single StateChange event is fired at the end, when scope gets disposed.Parameters:
- TAction action
Action object to dispatch
- TAction action
- void DispatchImmediate <TAction>(TAction action)
Dispatch and cause to fire StateChange immediately. Even when under multi-dispatcher scope, there may be some changes that makes sense to be reflected in UI immediately. Typically DispatchImmediately is intended to dispatch in-progress actions before actual dispatches begin. Warning: -
Dispatching immediately in middle of dispatch sequence may cause UI to render partally correct state.
Parameters:
- TAction action
Action object to dispatch
- TAction action
- Urunium.Redux.Logic.IMultiDispatcher BeginScope ()
Begin a nested scope of multi-dispatcher.
class Urunium.Redux.Logic.LogicBase<TState, TAction>
Abstract base class for logics. Implementing vanilla Urunium.Redux.Logic.ILogic<TState, TAction> works but leaves more to be desired. LogicBase splits Preprocess into Transformation and Validation. Gives ability to replace any of Preprocess/Processing steps with custom implementation.
Methods
-
void Cancel <TCancel>(TCancel cancelAction)
Cancel a processParameters:
- TCancel cancelAction
Action used to cancel this process.
- TCancel cancelAction
Properties and Fields
- Type CancelType
Type of action that when dispatched will cancel this process
- uint Priority
Priority of logic. Priority is calculated in descending order. i.e. Greater the number higher the priority
- bool IsLongRunning
Indicate that this is a long running process, so other logics must continue while this is running in background (i.e. don't wait for it to complete). Long running processes are given separate thread, through use of: System.Threading.Tasks.TaskCreationOptions.LongRunning . Implementor doesn't need to concern with running it in separate thread. Note: - PreProcess(Urunium.Redux.IStore<TState> store, TAction action) cannot be long running.
- Only Process(System.Func<TState> getState, TAction action, Urunium.Redux.Logic.IMultiDispatcher dispatcher) can be long running.
class Urunium.Redux.Logic.LogicStoreExtension
Extension class to configure Logic in store.
Static Methods
-
IStore<TState> ConfigureLogic <TState>(Urunium.Redux.IStore<TState> originalStore, System.Action<Urunium.Redux.Logic.ILogicConfiguration<TState>> configurator)
Enhance your store to handle business logics.Returns: Enhanced store, that now can handle business logics.
Parameters:
-
IStore<TState> originalStore
Original store that will be enhanced with ability to handle business logic. -
Action<ILogicConfiguration<TState>> configurator
Instance of Urunium.Redux.Logic.ILogicConfiguration<TState> .
-
class Urunium.Redux.Logic.MultiDispatcher
Factory class to create Urunium.Redux.Logic.IMultiDispatcher .
Examples
Example of how multi-dispatcher generally will be used.
using(var dispatcher = MultiDispatcher.Create(store))
{
dispatcher.DispatchImmediately("Long runing process has began");
dispatcher.Dispatch("1");
dispatcher.Dispatch("2");
dispatcher.Dispatch("3");
}
Static Methods
-
Urunium.Redux.Logic.IMultiDispatcher Create <TState>(Urunium.Redux.IStore<TState> store)
Create an instance of IMultiDispatcherReturns: Instance of Urunium.Redux.Logic.IMultiDispatcher
Parameters:
- IStore<TState> store
Instance of store for which multi-dispatcher needs to be created.
- IStore<TState> store
class Urunium.Redux.Logic.PoisonPill
This action is meant to be used in conjunction with Logic, for a system which needs a way to gracefully cancel everything things that are in progress. All logic must handle this Action type, and cancel it's process when received. Meaning all the logic currently running can be killed by dispatching PoisionPill at once.
Constructors
-
Urunium.Redux.Logic.PoisonPill (string reason, [bool kill])
Instanciate new Urunium.Redux.Logic.PoisonPillParameters:
-
string reason
Reason describing why this poison-pill was supplied. -
bool kill (optional, default: True)
Decides fatality of poison-pill. Setting Kill to false will just cancel all task in progress but not kill the system
-
Properties and Fields
- string Reason
Reason describing why this poison-pill was supplied.
- bool Kill
Decides fatality of poison-pill. Setting Kill to false will just cancel all task in progress but not kill the system.
class Urunium.Redux.Logic.PreProcessResult
Result of preprocessing logic.
Constructors
-
Urunium.Redux.Logic.PreProcessResult (bool continueToNext, Object action)
Immutable constructor to instanciate new Urunium.Redux.Logic.PreProcessResult .Parameters:
-
bool continueToNext
-
Object action
-
Properties and Fields
- bool ContinueToNextStep
Whether or not continue to execute the chain of logic.
- Object Action
Action that was dispatched
class Urunium.Redux.Logic.ValidationException
Extends Exception
Exception representing something is invalid with dispatched action.
Constructors
-
Urunium.Redux.Logic.ValidationException (string message)
Create new instance of Urunium.Redux.Logic.ValidationExceptionParameters:
- string message
Exception Message, typically a summary message implying something went wrong.
- string message
Properties and Fields
- IEnumerable<Urunium.Redux.Logic.ValidationDetails> ValidationDetails
Details explaining what are invalid.
class Urunium.Redux.Logic.ValidationDetails
Details of validation result
Constructors
-
Urunium.Redux.Logic.ValidationDetails (string key, string message)
Immutable CtorParameters:
-
string key
-
string message
-
Properties and Fields
- string Key
Associates a validation message with a key. Typically Key may be a name of UI (form) field, to which message needs to be associated. Recommended convention is to use "*" when validation doesn't associate with any particular field.
- string Message
Explation of the reason for invalid.
class Urunium.Redux.Logic.ValidationResult
Validation Result
Properties and Fields
- bool IsValid
Use to check if Action was valid or not.
- Urunium.Redux.Logic.ValidationException Error
Use to determine what are the reason Action is invalid. Is set to null if IsValid is true.
Static Methods
- Urunium.Redux.Logic.ValidationResult Success ()
If action being dispatched is valid.
-
Urunium.Redux.Logic.ValidationResult Failure (Urunium.Redux.Logic.ValidationException error)
If action being dispatched is invalid.Parameters:
- Urunium.Redux.Logic.ValidationException error
class Urunium.Redux.Enhance.StoreEnhancer<TState>
Gives ability to intercept and enhance store functionalities. This class works in Russian doll model, each enhancer wrapping an inner enhancer, until the inner most object is instance of Urunium.Redux.Store<TState> itself.LogicEnhanceris an example of how enhancer can be used.
Examples
// Store Enhancer, that gives filtered todo items based on VisibilityFilter
// when a accessing State property.
class FilterTodoItems : StoreEnhancer<Todo>
{
public FilterTodoItems(IStore<Todo> store) : base(store)
{
}
// override what gets returned when State property is accessed.
protected override Todo OnState(Func<Todo> forward)
{
var fullState = forward();
return new Todo(fullState.VisibilityFilter, FilterItems(fullState));
}
private List<TodoItem> FilterItems(Todo state)
{
switch (state.VisibilityFilter)
{
case Filter.Completed:
return state.Todos.Where(x => x.IsComplete).ToList();
case Filter.InProgress:
return state.Todos.Where(x => !x.IsComplete).ToList();
default:
return state.Todos;
}
}
}
// Usage:
IStore<Todo> store = new Store<Todo>(rootReducer, new Todo(Filter.ShowAll, new List<TodoItem>()))
.EnhanceWith(typeof(FilterTodoItems));
store.Dispatch(new AddTodo("Sleep"));
store.Dispatch(new AddTodo("Eat"));
store.Dispatch(new AddTodo("Drink"));
store.Dispatch(new SetVisibilityFilter(Filter.Completed));
// Since all todo Item is inprogress state.
Assert.AreEqual(0, store.State.Todos.Count);
store.Dispatch(new ToggleTodo(0));
// Since one of the item is marked completed.
Assert.AreEqual(1, store.State.Todos.Count);
Constructors
-
Urunium.Redux.Enhance.StoreEnhancer<TState> (Urunium.Redux.IStore<TState> store)
Constructor of Urunium.Redux.Enhance.StoreEnhancer<TState> that enhances store object.Parameters:
- IStore<TState> store
Urunium.Redux.IStore<TState> instance that needs to be enhanced.
- IStore<TState> store
Methods
-
void Dispatch <TAction>(TAction action)
Dispatch action to reducers, with enhancements.Parameters:
- TAction action
- TEnhancer Find <TEnhancer>()
Locate a particular store enhancer, applied to current store. Note: - Search is inwards, i.e while locating, traversal is done from outer most enhacer to inner-most store.
-
This is implementation detail of IStore extension method :
Returns: Enhancer instance if found, or null.
Events
- EventHandler<EventArgs> StateChanged
Get notified when state changes, with enhancements.
Properties and Fields
- TState State
Enhanced State
class Urunium.Redux.Enhance.StoreExtension
Extension methods for Urunium.Redux.IStore<TState> to enhance store instances.
Static Methods
-
IStore<TState> EnhanceWith <TState>(Urunium.Redux.IStore<TState> originalStore, Type[] enhancerTypes)
Applies enhancers to given store.Returns: instance of IStore after applying all enhancers.
Parameters:
-
IStore<TState> originalStore
IStore instance -
Type[] enhancerTypes
All store enhancers must inherit from
-
-
TEnhancer FindEnhancer <TEnhancer, TState>(Urunium.Redux.IStore<TState> originalStore)
Locate a particular store enhancer applied to current store. Note: Search is inwards, i.e while locating, traversal is done from outer most enhacer to inner-most IStore.Returns: Enhancer instance if found, or null.
Parameters:
- IStore<TState> originalStore
Instance of IStore from which Enhancer is to be located.
- IStore<TState> originalStore
interface Urunium.Redux.Compose.ISubTreeReducer<TState, TPart>
Reducer that works on a part (sub-tree) of application state. Hence helps in dividing reducers into small reducers, processing independently smaller part of the state tree.
Properties and Fields
- Expression<Func<TState, TPart>> PropertySelector
Expression representing the property of TState class, that this subtree reducer deals with.
class Urunium.Redux.Compose.ReducerComposer<TState>
Root reducer that will compose various reducers.
Constructors
Methods
-
Urunium.Redux.Compose.ReducerComposer<TState> AddStateReducer (Urunium.Redux.IReducer<TState> stateReducer)
Add a reducer.Returns: ReducerComposer for fluent-api.
Parameters:
- IReducer<TState> stateReducer
-
Urunium.Redux.Compose.ReducerComposer<TState> AddSubTreeReducer <TPart>(Urunium.Redux.Compose.ISubTreeReducer<TState, TPart> subTreeReducer)
Add a reducer that works in part/property (sub-tree) of application's state.Returns: ReducerComposer for fluent-api.
Parameters:
- ISubTreeReducer<TState, TPart> subTreeReducer
Instance of ISubTreeReducer
- ISubTreeReducer<TState, TPart> subTreeReducer
-
TState Apply (TState previousState, Object action)
Apply action to state using registered reducers.Returns: Resulting state after applying action.
Parameters:
-
TState previousState
State that needs to be transformed -
Object action
Action that needs to be applied to state.
-
class Urunium.Redux.Compose.SubTreeToFullTreeAdapter<TState, TPart>
Helps adapt a subtree reducer into full state tree reducer.
Constructors
-
Urunium.Redux.Compose.SubTreeToFullTreeAdapter<TState, TPart> (Urunium.Redux.Compose.ISubTreeReducer<TState, TPart> subTreeReducer)
Constructor for SubTreeToFullTreeAdapterParameters:
- ISubTreeReducer<TState, TPart> subTreeReducer
Instance of subtree reducer that needs to adapt.
- ISubTreeReducer<TState, TPart> subTreeReducer
Methods
-
TState Apply (TState previousState, Object action)
Apply subtree reducer and adapt to application stateReturns: New state of property
Parameters:
-
TState previousState
Old state of property -
Object action
Action to be applied
-