Startup Services
What Are They?
Section titled “What Are They?”Startup services run immediately after the dependency injection container is built. They support full constructor injection like any other service, which makes them the perfect place to hook global application events — wiring up a logout handler, warming a cache, subscribing to a message bus, or scheduling jobs.
IShinyStartupTask.Start() is intentionally synchronous. The platform does not wait for your app startup to finish, so any async work you kick off here runs in a fire-and-forget fashion. If you block for too long, the OS can kill your app before it finishes launching.
Implementing a Startup Task
Section titled “Implementing a Startup Task”using Shiny;
namespace MyApp.Infrastructure;
public class MyStartupService : IShinyStartupTask{ readonly ILogger<MyStartupService> logger;
public MyStartupService(ILogger<MyStartupService> logger) { this.logger = logger; }
public void Start() { // Hook global events, warm caches, etc. this.logger.LogInformation("App started"); }}Registration
Section titled “Registration”Tag the class with [Singleton] from Shiny.Extensions.DependencyInjection and call services.AddGeneratedServices() once during host build. The source generator emits a registration that exposes every interface the class implements (including IShinyStartupTask) — no reflection, AOT-clean.
using Shiny;
[Singleton]public class MyStartupService : IShinyStartupTask{ // ...}
// wherever you build your service collectionbuilder.Services.AddGeneratedServices();If you prefer explicit registration:
builder.Services.AddSingleton<MyStartupService>();builder.Services.AddSingleton<IShinyStartupTask>(sp => sp.GetRequiredService<MyStartupService>());Either way, Start() runs automatically when the Shiny host runs.