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
  • 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 Extensions (DI, Stores, and Web Hosting) to help generate service registrations, configure stores, and follow best practices directly in your IDE.

Claude Code

Terminal window
claude plugin add github:shinyorg/skills

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