Shiny.Extensions.Reflector 4.0.0-beta-0004
Shiny Extensions
Dependency Injection Extensions
- Source generate all attributed classes to a single add file - saves you the boilerplate
- Factory-form emission - generated registrations expand the constructor at compile time (no reflection, AOT-clean) so resolve chains like
OnResolvedcompose naturally ActivatorUtilities-style constructor selection ([ActivatorUtilitiesConstructor]and[FromKeyedServices]honored)- Multiple interfaces via explicit forwarders (no reflection)
- Supports open generics and keyed services
OnResolved<T>(hook)chain extension for one-shot post-construction hooks
The Results
THIS:
using Microsoft.Extensions.DependencyInjection;
using Shiny;
// given the following code from a user
namespace Sample
{
public interface IStandardInterface;
public interface IStandardInterface2;
[Service(ServiceLifetime.Singleton)]
public class ImplementationOnly;
[Service(ServiceLifetime.Transient, "ImplOnly")]
public class KeyedImplementationOnly;
[Service(ServiceLifetime.Singleton)]
public class StandardImplementation : IStandardInterface;
[Service(ServiceLifetime.Scoped, "Standard")]
public class KeyedStandardImplementation : IStandardInterface;
[Service(ServiceLifetime.Singleton)]
public class MultipleImplementation : IStandardInterface, IStandardInterface2;
[Service(ServiceLifetime.Scoped)]
public class ScopedMultipleImplementation : IStandardInterface, IStandardInterface2;
[Service(ServiceLifetime.Scoped, "KeyedGeneric")]
public class TestGeneric<T1, T2>
{
public T1 Value1 { get; set; }
public T2 Value2 { get; set; }
}
}
GENERATES THIS:
// <auto-generated />
using global::Microsoft.Extensions.DependencyInjection;
using global::Shiny;
namespace Sample
{
public static class __GeneratedRegistrations
{
public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddGeneratedServices(
this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services
)
{
services.AddSingleton<global::Sample.ImplementationOnly>();
services.AddKeyedTransient<global::Sample.KeyedImplementationOnly>("ImplOnly");
services.AddSingleton<global::Sample.IStandardInterface, global::Sample.StandardImplementation>();
services.AddKeyedScoped<global::Sample.IStandardInterface, global::Sample.KeyedStandardImplementation>("Standard");
services.AddSingletonAsImplementedInterfaces<global::Sample.MultipleImplementation>();
services.AddScopedAsImplementedInterfaces<global::Sample.ScopedMultipleImplementation>();
services.AddKeyedScoped(typeof(global::Sample.TestGeneric<,>), "KeyedGeneric");
return services;
}
}
}
Setup
- Install the NuGet package
Shiny.Extensions.DependencyInjection - Add the following using directive:
// during your app startup - use your service collection builder.Services.AddGeneratedServices(); - Add the
[Service(ServiceLifetime.Singleton, "optional key")]attribute to your classes and specify the lifetime and optional key
Stores
- Cross-platform key/value store with support for
- Android/iOS/Windows - Preferences & Secure Storage
- Web - Local Storage
- In Memory
- Source-generated
[Bind]attribute on partial properties - emits getter/setter bodies that round-trip through the store (no INPC required, no runtime reflection, fully AOT) - Static
Shiny.Stores.Default/Secure/Keyed(...)accessor for direct ad-hoc reads/writes - Implement
IKeyValueStoreto plug in your own store
Setup
- Install the NuGet package
Shiny.Extensions.Stores - Register at startup:
builder.Services.AddShinyStores(); - Define your settings as a
partialclass with[Bind]partial properties: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; } } - Inject
AppSettingsanywhere. Set properties — they persist. Read properties — they come from the store.
Or skip the class and use the static accessor:
Shiny.Stores.Default.Set("theme", "dark");
var theme = Shiny.Stores.Default.Get<string>("theme");
Available Stores Per Platform
| Platform | Key | Description |
|---|---|---|
| Android | StoreKeys.Default |
Preferences |
| Android | StoreKeys.Secure |
Secure Storage |
| iOS | StoreKeys.Default |
NSUserDefaults |
| iOS | StoreKeys.Secure |
Keychain |
| Windows | StoreKeys.Default |
ApplicationData.LocalSettings |
| Windows | StoreKeys.Secure |
Secure Storage |
| WebAssembly | StoreKeys.Default |
localStorage |
| WebAssembly | "session" |
sessionStorage |
| All | any | In-memory dictionary (great for testing) |
[!NOTE] For WebAssembly, install the
Shiny.Extensions.Stores.Webpackage and addservices.AddShinyWebAssemblyStores()to your service collection.
Web Hosting Extensions
- Merges service container build and post build scenarios into a single class using
IWebModule
Setup
- Install the NuGet package
Shiny.Extensions.WebHosting - Add a web module by implementing
IWebModule:using Shiny; public class MyWebModule : IWebModule { public void Add(WebApplicationBuilder builder) { // Register your services here } public void Use(WebApplication app) { // Configure your middleware/endpoints here } } - In your application hosting startup, add the following:
using Shiny; var builder = WebApplication.CreateBuilder(args); builder.AddInfrastructureModules(new MyWebModule()); var app = builder.Build(); app.UseInfrastructureModules();
MAUI Hosting Extensions
- Module-based MAUI app configuration with
IMauiModule - Static
Host.Servicesfor accessing the service provider anywhere - Platform lifecycle hooks via
ILifecycleExecutor(foreground/background events, activity results, etc.)
Setup
- Install the NuGet package
Shiny.Extensions.MauiHosting - Create a MAUI module by implementing
IMauiModule:using Shiny; public class MyMauiModule : IMauiModule { public void Add(MauiAppBuilder builder) { // Register your services here } public void Use(IPlatformApplication app) { // Post-build initialization here (do NOT block) } } - In your
MauiProgram.cs:using Shiny; var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .AddInfrastructureModules(new MyMauiModule()); return builder.Build(); - Access services anywhere via
Host.Services
Additional Libraries Used
- Shiny Reflector - Reflection without the actual reflection
NuGet Packages
| Package | Description |
|---|---|
Shiny.Extensions.DependencyInjection |
Attribute-driven DI registration with source generators |
Shiny.Extensions.Stores |
Cross-platform key/value store abstraction |
Shiny.Extensions.Stores.Web |
Blazor WebAssembly localStorage/sessionStorage |
Shiny.Extensions.WebHosting |
ASP.NET modular web hosting with IWebModule |
Shiny.Extensions.MauiHosting |
MAUI modular hosting with IMauiModule and platform lifecycle hooks |
Showing the top 20 packages that depend on Shiny.Extensions.Reflector.
| Packages | Downloads |
|---|---|
|
Shiny.Extensions.Stores
Store anything in a key/value store - Abstractions for iOS, Android and Windows preferences/secure storage
|
1 |
.NET 10.0
- No dependencies.
| Version | Downloads | Last updated |
|---|---|---|
| 5.1.1 | 1 | 06/22/2026 |
| 5.1.0 | 1 | 06/22/2026 |
| 5.1.0-beta-0054 | 1 | 06/22/2026 |
| 5.1.0-beta-0052 | 1 | 06/13/2026 |
| 5.1.0-beta-0051 | 1 | 06/13/2026 |
| 5.0.0 | 1 | 06/13/2026 |
| 5.0.0-beta-0052 | 1 | 06/13/2026 |
| 5.0.0-beta-0051 | 1 | 06/13/2026 |
| 4.1.1 | 1 | 06/13/2026 |
| 4.1.0 | 1 | 06/13/2026 |
| 4.0.0 | 1 | 06/13/2026 |
| 4.0.0-beta-0063 | 1 | 06/13/2026 |
| 4.0.0-beta-0062 | 1 | 06/13/2026 |
| 4.0.0-beta-0061 | 1 | 06/13/2026 |
| 4.0.0-beta-0060 | 1 | 06/13/2026 |
| 4.0.0-beta-0059 | 1 | 06/13/2026 |
| 4.0.0-beta-0058 | 1 | 06/13/2026 |
| 4.0.0-beta-0057 | 1 | 06/13/2026 |
| 4.0.0-beta-0056 | 1 | 06/13/2026 |
| 4.0.0-beta-0041 | 1 | 06/13/2026 |
| 4.0.0-beta-0005 | 1 | 06/13/2026 |
| 4.0.0-beta-0004 | 1 | 06/13/2026 |
| 4.0.0-beta-0003 | 1 | 06/13/2026 |
| 4.0.0-beta-0002 | 1 | 06/13/2026 |