Skip to content

TimeWarpEngineering/timewarp-builder

Repository files navigation

TimeWarp.Builder

NuGet NuGet Downloads CI/CD License: Unlicense

Fluent builder interfaces and Kotlin-inspired scope extensions for .NET.

Installation

dotnet add package TimeWarp.Builder --prerelease

Requirements

  • .NET 10.0 or later
  • Fully AOT- and trim-compatible (no reflection, no dynamic code)

Interfaces

IBuilder<T>

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();

INestedBuilder<TParent>

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);

Scope Extensions

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 vs Apply

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 configuration

Also

Executes an action on the object and returns the original object.

var builder = new AppBuilder()
    .Also(b => logger.LogDebug("Building app..."))
    .Configure(options);

Apply

Configures the object and returns the original object.

app.Map("status", handler)
   .Apply(r => r.AsQuery());

Let

Transforms the object to a different type.

int length = "hello".Let(s => s.Length);  // 5

Run

Executes 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.

Used By

Testing

Tests are TimeWarp.Jaribu runfiles under tests/. Run them all with dev test, or any file directly:

dotnet run tests/scope-extensions.also.cs

Unlicense

This is free and unencumbered software released into the public domain — see LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages