ワンクリックで
shiny-stores
// Generate and configure Shiny Stores for .NET - cross-platform key/value stores with source-generated property binding for mobile, desktop, and Blazor WebAssembly
// Generate and configure Shiny Stores for .NET - cross-platform key/value stores with source-generated property binding for mobile, desktop, and Blazor WebAssembly
Generate and configure Shiny MAUI Hosting for .NET - modular MAUI app configuration with IMauiModule, static Host.Services access, IAppSupport (device info + orientation/culture/timezone change events + programmatic orientation lock), and IAppStore (cross-platform store version lookups and deep links for Apple, Google, Microsoft stores)
Generate and configure Shiny DI for .NET - attribute-driven service registration with source generators, keyed services, categories, and multi-interface support
Generate code using Shiny Reflector for AOT-compliant, source-generated property access, JSON serialization, and assembly info generation in .NET applications
Generate and configure Shiny Web Hosting for .NET - modular ASP.NET Core application configuration with IWebModule for clean service registration and middleware setup
| name | shiny-stores |
| description | Generate and configure Shiny Stores for .NET - cross-platform key/value stores with source-generated property binding for mobile, desktop, and Blazor WebAssembly |
| auto_invoke | true |
| triggers | ["IKeyValueStore","AddShinyStores","AddShinyWebAssemblyStores","StoreKeys","Shiny.Stores","BindAttribute","Shiny.Extensions.Stores","Shiny.Extensions.Stores.Web"] |
You are an expert in Shiny Extensions Stores, a .NET library providing cross-platform key/value store abstraction with source-generated property binding.
Invoke this skill when the user wants to:
[Bind] source generatorDocumentation: https://shinylib.net/extensions/stores/
Repository: https://github.com/shinyorg/Shiny.Extensions
Packages: Shiny.Extensions.Stores, Shiny.Extensions.Stores.Web
Stores are registered as keyed singletons in DI using StoreKeys constants:
| Key | Platform | Implementation |
|---|---|---|
StoreKeys.Default ("settings") | Android | SharedPreferences |
StoreKeys.Default ("settings") | iOS/macOS | NSUserDefaults |
StoreKeys.Default ("settings") | Windows | ApplicationData.LocalSettings |
StoreKeys.Default ("settings") | Blazor | localStorage |
StoreKeys.Secure ("secure") | Android | EncryptedSharedPreferences |
StoreKeys.Secure ("secure") | iOS/macOS | Keychain |
// Mobile / desktop — platform-native stores
services.AddShinyStores();
// Blazor WebAssembly — localStorage (still needs UseShinyStores after Build,
// because IJSRuntime is only available post-build)
services.AddShinyWebAssemblyStores();
On mobile/desktop you do not need a post-build UseShinyStores() call.
Shiny.Stores.Default / Shiny.Stores.Secure are self-bootstrapping: on first
access they lazily create the platform-native store (SharedPreferences /
NSUserDefaults / Keychain / DPAPI / MemoryKeyValueStore). AddShinyStores()
just registers those same instances into DI so keyed IKeyValueStore injections
share them.
For Blazor (where the store needs IJSRuntime from the built provider) call
host.Services.UseShinyStores() after host.Build() to snapshot the keyed
IKeyValueStore registrations into the static accessor.
Shiny.Stores AccessorThe simplest way to read/write — self-bootstraps on first access. No initialization required for mobile/desktop.
Shiny.Stores.Default.Set("theme", "dark");
var theme = Shiny.Stores.Default.Get<string>("theme");
Shiny.Stores.Secure.Set("token", "abc123");
// Arbitrary keyed stores (must be registered with Stores.Register or via DI + UseShinyStores)
Shiny.Stores.Keyed("my-store").Set("k", "v");
// Swap any key for a test double or custom backend
Shiny.Stores.Register(StoreKeys.Default, new MemoryKeyValueStore());
Shiny.Stores.Register("redis", new RedisKeyValueStore(...));
// Or snapshot keyed IKeyValueStore registrations from a built provider:
serviceProvider.UseShinyStores();
// Equivalent low-level call:
Shiny.Stores.Initialize(serviceProvider);
// Reset between tests:
Shiny.Stores.Reset();
public class SettingsService(
[FromKeyedServices(StoreKeys.Default)] IKeyValueStore settings,
[FromKeyedServices(StoreKeys.Secure)] IKeyValueStore secure
)
{
public void SaveTheme(string theme) => settings.Set("theme", theme);
public string GetTheme() => settings.Get<string>("theme") ?? "light";
}
[Bind] PropertiesThe DI source generator (from Shiny.Extensions.DependencyInjection) recognizes [Bind] on partial properties and emits getter/setter bodies that round-trip through the static Shiny.Stores accessor.
using Shiny;
[Singleton]
public partial class AppSettings
{
[Bind] // default store
public partial string Theme { get; set; }
[Bind("secure")] // secure store
public partial string Token { get; set; }
[Bind(Key = "ui_density")] // override storage key
public partial int Density { get; set; }
}
No INotifyPropertyChanged, no runtime reflection. Generated property bodies call Shiny.Stores.Default/Secure/Keyed(...).Get<T>(...) and .Set(...).
store.Get<T>(key, defaultValue); // Get with default
store.GetRequired<T>(key); // Throws if not found
store.SetOrRemove(key, value); // Removes if value is null
store.SetDefault<T>(key, value); // Only sets if key doesn't exist
store.IncrementValue(key); // Thread-safe integer increment
AddShinyStores() for mobile/desktop, AddShinyWebAssemblyStores() for Blazor[Singleton] + [Bind] partial properties over manual Set/Get calls[Bind] properties must be partial; properties must also be partial"secure" to [Bind("secure")]Shiny.Stores.Default/Secure/Keyed(...) for direct ad-hoc access[Bind] for settings classes — eliminates boilerplate, no INPC needed, AOT-clean[Bind("secure")] for sensitive valuesShiny.Stores self-bootstraps on first access. UseShinyStores() is only needed for Blazor (because IJSRuntime requires the built provider) or when you've registered custom keyed IKeyValueStores in DI that you want snapshotted into the static accessorStores.Register in tests — pair with Stores.Reset() between tests to swap in MemoryKeyValueStore or any custom double