StateManagementSharp 1.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package StateManagementSharp --version 1.1.0
                    
NuGet\Install-Package StateManagementSharp -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="StateManagementSharp" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="StateManagementSharp" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="StateManagementSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add StateManagementSharp --version 1.1.0
                    
#r "nuget: StateManagementSharp, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package StateManagementSharp@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=StateManagementSharp&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=StateManagementSharp&version=1.1.0
                    
Install as a Cake Tool

StateManagementSharp

NuGet NuGet downloads CI License: MIT

StateManagementSharp is a lightweight, dependency-injection-native library for centralized, app-wide state in .NET applications. It organizes shared state into a Store composed of feature Modules, and changes flow through an explicit Action → Mutation pipeline, so state transitions stay predictable and easy to follow.

It is conceptually inspired by store/module/action/mutation architectures (such as Vuex and NGXS), but it is a pure .NET library: no JavaScript runtime, no Vue/Angular dependency, and it builds directly on Microsoft.Extensions.DependencyInjection.

What it is (and what it is not)

It is a small, structured container for state that is shared across many parts of an app — the kind of state that does not belong to a single view or view model (session/profile, app context, feature-level domain state) — plus a disciplined way to read and change it.

It is not a reactive UI framework. In this version, changing state does not automatically raise change notifications: after dispatching an action you read the current state (for example, refreshing bindable properties in a view model). Automatic change notification is planned for a future release (see Roadmap).

When to use it

  • You have app-wide or cross-view-model state and want a single, predictable place for it.
  • You want explicit, traceable state transitions: actions describe intent, and mutations are the only code that changes state.
  • You already use Microsoft.Extensions.DependencyInjection and want state management that fits naturally into it.
  • You are building .NET MAUI, ASP.NET Core, worker, or console apps and want the same model across all of them.

When NOT to use it

  • You only need per-view-model local state — the MVVM Toolkit is simpler and sufficient.
  • You need automatic UI updates today from state changes — that is not implemented yet.
  • You need Redux DevTools, time-travel debugging, or effects middleware now — consider Fluxor.
  • You want reactive streams over state — consider ReactiveUI.

How it compares

Option Focus Relationship to StateManagementSharp
CommunityToolkit.Mvvm (MVVM Toolkit) Observable properties, commands, and messaging per view model Complementary, not a replacement. Keep using it for view-model state and commands; use StateManagementSharp for the shared, app-wide state those view models read from.
Fluxor Flux/Redux for .NET, strong in Blazor, with effects and Redux DevTools More feature-complete and Blazor-proven. StateManagementSharp is smaller, module-oriented, and aimed at the general .NET/MAUI case; it does not (yet) offer DevTools or effects.
ReactiveUI Reactive (Rx) MVVM and event pipelines A different mental model. Choose StateManagementSharp if you want a store/module structure without adopting Rx.
A custom singleton service + DI Whatever you hand-roll StateManagementSharp is essentially a structured version of that pattern: modules, typed Dispatch/Commit, and a single mutation path. If one shared service is all you need, a plain singleton may be enough; the structure pays off as shared state grows.

Using it in .NET MAUI

MAUI apps often need state that outlives a single page and is shared by several view models — session and profile data, an app-context/busy flag, feature state. StateManagementSharp gives that state a single home and a predictable update path, registered through the same DI container MAUI already uses.

Because there is no automatic change notification yet, a view model reads the store after dispatching (see the MAUI example below). This keeps the 1.x line honest and simple; reactive binding is on the roadmap.

Features

  • Store-based application state with Store<TRootState>.
  • Feature modules through ModuleBase<TState, TRootState>.
  • Asynchronous actions through Action<TState, TRootState>.
  • State updates through Mutation<TState, TPayload>.
  • Typed module dispatch with Dispatch<TAction>() and typed commits with Commit<TMutation, TPayload>(payload).
  • Name-based Dispatch(actionName) and Commit(mutationName, payload) where supported.
  • DI setup with AddStateManagementSharp(params Assembly[]) and assembly scanning for concrete action types.
  • Runs on .NET MAUI, ASP.NET Core / Web API, worker services, and console apps.
  • Built directly on Microsoft.Extensions.DependencyInjection.

Installation

Install the package from NuGet:

dotnet add package StateManagementSharp --version 1.1.0

The NuGet package contains the core StateManagementSharp library. The MAUI sample app is included in this repository as an example and is not part of the package.

Basic Setup

Register StateManagementSharp services and your store in DI:

builder.Services.AddStateManagementSharp(typeof(InternalStore).Assembly);
builder.Services.AddSingleton<InternalStore>();

AddStateManagementSharp registers the library factories and scans the provided assemblies for action implementations that should be resolved from DI.

Minimal Example

The following example shows the core pattern: define a root state, a module state, a module, a mutation, an action, and a store.

using Microsoft.Extensions.DependencyInjection;
using StateManagementSharp;

public sealed class AppState : RootState
{
    private AppStore Store { get; }

    public CounterState Counter => Store.Counter.State!;

    public AppState(AppStore store)
    {
        Store = store;
    }
}

public sealed record CounterState(int Value) : State;

public sealed class CounterModule : ModuleBase<CounterState, AppState>
{
    public CounterModule(AppStore store, MutationFactory mutationFactory, ActionFactory actionFactory)
        : base(store, mutationFactory, actionFactory)
    {
    }

    public override void CreateState()
    {
        State = new CounterState(0);
    }

    public override void DisposeState()
    {
        State = null;
    }
}

public sealed class IncrementMutation : Mutation<CounterState, int>
{
    public CounterState Apply(CounterState state, int amount)
    {
        return state with { Value = state.Value + amount };
    }
}

public sealed class IncrementAction : StateManagementSharp.Action<CounterState, AppState>
{
    public Task Execute(ActionContext<CounterState, AppState> context, object? payload)
    {
        var amount = payload is int value ? value : 1;

        context.Commit<IncrementMutation, int>(amount);

        return Task.CompletedTask;
    }
}

public sealed class AppStore : Store<AppState>
{
    public CounterModule Counter { get; private set; } = null!;

    private MutationFactory MutationFactory { get; }
    private ActionFactory ActionFactory { get; }

    public AppStore(MutationFactory mutationFactory, ActionFactory actionFactory)
    {
        MutationFactory = mutationFactory;
        ActionFactory = actionFactory;
        State = new AppState(this);
    }

    public override void InitializeStore()
    {
        BindModules();
        BootstrapModules();
    }

    protected override void BindModules()
    {
        Counter = new CounterModule(this, MutationFactory, ActionFactory);
        Modules = [Counter];
    }

    public override void InitState()
    {
        State = new AppState(this);
    }
}

Use the store through DI:

var services = new ServiceCollection();

services.AddStateManagementSharp(typeof(AppStore).Assembly);
services.AddSingleton<AppStore>();

await using var provider = services.BuildServiceProvider();

var store = provider.GetRequiredService<AppStore>();
store.InitializeStore();

await store.Counter.Dispatch<IncrementAction>(5);

var value = store.State?.Counter.Value;

.NET MAUI Usage

The sample app registers the store in MauiProgram.cs:

builder.Services.AddStateManagementSharp(typeof(InternalStore).Assembly);
builder.Services.AddSingleton<InternalStore>();

A plain ViewModel can receive the store from DI, initialize it, dispatch actions, and read the current state. Note that state changes do not raise notifications yet, so the ViewModel reads the store after each dispatch:

public sealed class MainPageViewModel
{
    private readonly InternalStore _store;

    public MainPageViewModel(InternalStore store)
    {
        _store = store;
        _store.InitializeStore();
    }

    public async Task LoadAsync()
    {
        await _store.ProfileModule.Dispatch<LoadProfileAction>();

        // Read current state after dispatch (no automatic change notification yet).
        var profile = _store.State?.ProfileState;
        var firstName = profile?.FirstName;
    }
}

Web API And Console Usage

StateManagementSharp uses Microsoft DI, so the setup is the same in ASP.NET Core, worker services, and console apps:

services.AddStateManagementSharp(typeof(AppStore).Assembly);
services.AddSingleton<AppStore>();

Register the store as a singleton for app-wide state. Scoped stores are also possible when the application owns the lifecycle and state boundaries.

Sample App

The MAUI sample is located at:

SAMPLE/StateManagementSharp.Sample.Maui

It demonstrates:

  • Store/InternalStore.cs and Store/InternalState.cs.
  • AppContext and Profile modules.
  • Actions and mutations for initializing app context, toggling busy state, loading a profile, and clearing a profile.
  • DI registration in MauiProgram.cs.
  • Store usage from MainPageViewModel.

Build

dotnet restore StateManagementSharp.sln
dotnet build StateManagementSharp/StateManagementSharp.csproj -c Release
dotnet build SAMPLE/StateManagementSharp.Sample.Maui/StateManagementSharp.Sample.Maui.csproj -f net10.0-android -c Debug

Tests

dotnet test StateManagementSharp.Tests/StateManagementSharp.Tests.csproj -c Release

Requirements

  • .NET 8.0 or later, or any target compatible with .NET Standard 2.0.
  • Microsoft.Extensions.DependencyInjection.
  • The .NET MAUI workload to build the sample app.

The package multi-targets netstandard2.0, net8.0, and net10.0, so it can be referenced from .NET Framework 4.6.2+, modern .NET, and .NET MAUI projects.

Roadmap

Planned, but not available yet:

  • Automatic change notification for bindable UI (implemented via Fody), so views update without manual refresh.
  • A dedicated StateManagementSharp.Maui integration package.
  • Logging/diagnostics middleware.

Known Limitations

  • StateManagementSharp is not a complete Vuex or NGXS clone.
  • No automatic UI change notification yet: read state after dispatch.
  • No built-in persistence, time-travel, or devtools support in the 1.x line.
  • Store lifecycle and scoping depend on the app's DI registration; register the store as a singleton for app-wide state.
  • Action and mutation discovery scans the store's own assembly, so the store, its modules, actions, and mutations are expected to live in the same assembly.

License

StateManagementSharp is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on StateManagementSharp:

Package Downloads
StateManagementSharp.Maui

.NET MAUI integration for StateManagementSharp: automatic, UI-thread-marshaled binding to store state via selectors, using Fody-woven bindable adapters.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.1 126 7/3/2026
2.0.0 116 7/3/2026
1.1.0 117 7/3/2026
1.0.0 123 5/27/2026

1.1.0: Multi-targeting (netstandard2.0, net8.0, net10.0) for broader compatibility. Source cleanup and improved NuGet metadata and README. No public API or functional changes.