Skip to content

Stores

Persist class properties across sessions with a single line of code. Shiny Stores provides a cross-platform key/value store abstraction that works on iOS, Android, Windows, and Blazor WebAssembly. Swap between Preferences, Secure Storage, Local Storage, and more — all behind the same API.

  • GitHub stars for shinyorg/extensions
  • NuGet Packages
    • NuGet package Shiny.Extensions.Stores
    • NuGet package Shiny.Extensions.Stores.Web
  • Unified key/value store interface across all platforms
  • Built-in stores for Preferences, Secure Storage, Local Storage, Session Storage, and In-Memory
  • Persistent services — bind INotifyPropertyChanged objects to a store and property changes are saved automatically
  • Integrates with Shiny Reflector for AOT-safe, reflection-free binding
  • Custom store support — implement IKeyValueStore for your own storage backend
  1. Install the NuGet package:

    Terminal window
    dotnet add package Shiny.Extensions.Stores
  2. Register stores in your DI container:

    builder.Services.AddShinyStores();
  3. For Blazor WebAssembly, also install and register the web stores:

    Terminal window
    dotnet add package Shiny.Extensions.Stores.Web
    builder.Services.AddShinyWebAssemblyStores();

Each platform provides different store implementations, identified by a string alias:

PlatformAliasImplementation
AndroidsettingsSharedPreferences
AndroidsecureEncryptedSharedPreferences
iOS / macOSsettingsNSUserDefaults
iOS / macOSsecureKeychain
WindowssettingsApplicationData.LocalSettings
WindowssecureSecure Storage
Blazor WebAssemblysettingslocalStorage
Blazor WebAssemblysessionsessionStorage
AllmemoryIn-memory dictionary (great for testing)

Inject IKeyValueStoreFactory to access any store by alias:

public class SettingsService(IKeyValueStoreFactory storeFactory)
{
public void SaveTheme(string theme)
{
var store = storeFactory.GetStore("settings");
store.Set("theme", theme);
}
public string GetTheme()
{
var store = storeFactory.GetStore("settings");
return store.Get<string>("theme", "light");
}
public void SaveToken(string token)
{
var store = storeFactory.GetStore("secure");
store.Set("auth_token", token);
}
}
store.Get<T>(key, defaultValue); // Get with a default fallback
store.GetRequired<T>(key); // Throws if key is not found
store.SetOrRemove(key, value); // Removes the key if value is null
store.SetDefault<T>(key, value); // Only sets if the key doesn't already exist
store.IncrementValue(key); // Thread-safe integer increment

Implement IKeyValueStore to create your own storage backend:

public class RedisKeyValueStore : IKeyValueStore
{
public string Alias => "redis";
public T? Get<T>(string key, T? defaultValue = default) { /* ... */ }
public void Set<T>(string key, T value) { /* ... */ }
public bool Contains(string key) { /* ... */ }
public bool Remove(string key) { /* ... */ }
public void Clear() { /* ... */ }
}

An AI skill is available for Shiny Stores to help configure key/value stores, persistent service binding, and follow best practices directly in your IDE.

Claude Code

Terminal window
claude plugin add github:shinyorg/skills

GitHub Copilot — Copy the shiny-stores skill file into your repository’s custom instructions.