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 of Action that needs to be applied to current state of Store. Applying an action may transform a state into new state.

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 of Action that needs to be applied to current state of Store. Applying an action may transform a state into new state.

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.

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

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 canceling

    Parameters:

    • 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 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


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.

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

  • 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

  • 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 process

    Parameters:

    • TCancel cancelAction
      Action used to cancel this process.

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


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:


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 IMultiDispatcher

    Returns: Instance of Urunium.Redux.Logic.IMultiDispatcher

    Parameters:

    • IStore<TState> store
      Instance of store for which multi-dispatcher needs to be created.

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.PoisonPill

    Parameters:

    • 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.ValidationException

    Parameters:

    • string message
      Exception Message, typically a summary message implying something went wrong.

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 Ctor

    Parameters:

    • 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

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.

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

  • 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 SubTreeToFullTreeAdapter

    Parameters:

    • ISubTreeReducer<TState, TPart> subTreeReducer
      Instance of subtree reducer that needs to adapt.

Methods

  • TState Apply (TState previousState, Object action)

    Apply subtree reducer and adapt to application state

    Returns: New state of property

    Parameters:

    • TState previousState
      Old state of property

    • Object action
      Action to be applied