A day in the shop
Follow one coffee shop from the code you write to the first cup.
You write the whole shop on one screen.
Registrations are attributes on a static partial class. The espresso machine only implements your own IWarmUp interface, so your domain code never references Awaiten.
[Container] [AsyncInitializer<IWarmUp>(nameof(IWarmUp.WarmUpAsync))] [Singleton<EspressoMachine>] [Scoped<Order>] [Transient<Cup>] public static partial class CoffeeShop;
- .NET CLI
- PackageReference
- Central Package Management
dotnet add package Awaiten
<PackageReference Include="Awaiten" Version="0.10.0" />
<PackageVersion Include="Awaiten" Version="0.10.0" />
<PackageReference Include="Awaiten" />
The compiler checks the shop.
If a cup would grab the machine before it is warm, the build stops. So does a missing registration, a cycle or a singleton holding on to a scoped service. Other containers find these at startup, or in production.
// the cup grabs the machine without waiting for it public sealed class Cup(Func<EspressoMachine> machine);
Func<Task<EspressoMachine>> and await it.The machine warms up, once.
InitializeAsync runs every async initializer in the graph. The shared espresso machine heats its boiler before anyone may use it.
await using CoffeeShop.Root shop = new(); await shop.InitializeAsync(); // the machine warms up
Every cup is ready.
Each order gets its own scope, like a web request. Each cup is made fresh, with a shot from the warm machine.
Cup cup = await shop.ResolveAsync<Cup>(); // a fresh cup, ready
Domain code stays yours
Registrations and async setup live on the container, so your services never reference Awaiten.
Plain C#, AOT clean
No reflection on any path, so native AOT and trimming just work.
Fits ASP.NET Core
The MS.DI bridge runs your container under the generic host, next to IServiceCollection.
Ready to open?
Build the coffee shop end to end, or map your IServiceCollection registrations over.