Fluent builder interfaces and Kotlin-inspired scope extensions for .NET.
dotnet add package TimeWarp.Builder --prerelease- .NET 10.0 or later
- Fully AOT- and trim-compatible (no reflection, no dynamic code)
Interface for standalone builders that create objects via Build(). TBuilt is covariant, so an IBuilder<Derived> can be used wherever an IBuilder<Base> is expected.
public class MyWidgetBuilder : IBuilder<Widget>
{
public Widget Build() => new Widget(_options);
}
// Usage
Widget widget = new MyWidgetBuilder()
.WithColor("blue")
.WithSize(10)
.Build();Interface for nested builders that return to a parent context via Done(). Done() performs three things: builds the child, hands the result to the parent, and returns the parent for continued chaining.
// Nested builder returns to parent after building
app.Map(route => route
.WithLiteral("deploy")
.WithParameter("env")
.Done()) // Returns to parent builder
.WithHandler(handler);Kotlin-inspired extension methods for fluent object manipulation. Because they attach to every type (unconstrained T), any object can participate in a fluent chain without its type opting in.
| Method | Returns | Use for |
|---|---|---|
Also |
The original object | Side effects mid-chain (logging, diagnostics) |
Apply |
The original object | Configuring the object mid-chain |
Let |
The transform result | Converting to a different type/value |
Run |
Nothing (void) |
Terminal action at the end of a chain |
Also and Apply are mechanically identical — both execute an action and return the original object. They exist separately to signal intent at the call site, mirroring Kotlin's also/apply distinction: use Apply when the action configures the object itself, and Also when the action is an incidental side effect like logging.
app.Map("status", handler)
.Apply(r => r.AsQuery()) // configures the route
.Also(r => logger.LogDebug("mapped {r}", r)); // side effect, not configurationExecutes an action on the object and returns the original object.
var builder = new AppBuilder()
.Also(b => logger.LogDebug("Building app..."))
.Configure(options);Configures the object and returns the original object.
app.Map("status", handler)
.Apply(r => r.AsQuery());Transforms the object to a different type.
int length = "hello".Let(s => s.Length); // 5Executes an action on the object with no return value. Terminal operation in a method chain.
app.Build().Run(a => a.RunAsync(args));All four methods throw ArgumentNullException when the delegate is null.
- TimeWarp.Nuru — route, endpoint, group, and key-binding builders implement
IBuilder<T>/INestedBuilder<TParent> - TimeWarp.Terminal
Tests are TimeWarp.Jaribu runfiles under tests/. Run them all with dev test, or any file directly:
dotnet run tests/scope-extensions.also.csThis is free and unencumbered software released into the public domain — see LICENSE.