Fluent API
Build, configure, and run workflows entirely in .NET code
Overview
The Aurora Workflows Fluent API (Aurora.Workflows.Fluent, targeting .NET Standard 2.0) lets you construct complete workflows in C# without using the designer. The API is chainable: every method returns a builder so calls can be composed in a single expression.
The entry point is the static class FluentWorkflow.
Getting Started
using Aurora.Workflows.Fluent;
using Aurora.Workflows.Tasks;
var workflow = FluentWorkflow
.Create("Hello World")
.TriggerOnce()
.Print("Hello, Aurora Workflows!")
.Build();
await workflow.StartAsync();
FluentWorkflow (Entry Point)
| Method | Description |
|---|---|
FluentWorkflow.Create(name, loggerFactory?) | Creates a new workflow builder. A root StartTask is created automatically. |
FluentWorkflow.Load(json, loggerFactory?) | Restores a workflow from a JSON string previously produced by Persist(). |
FluentWorkflowBuilder – Metadata & Triggers
| Method | Description |
|---|---|
.WithName(name) | Sets or overrides the workflow display name. |
.WithTags(params string[] tags) | Adds classification tags to the workflow. |
.ConfigureWorkflow(action) | Applies an arbitrary action on the underlying IWorkflow. |
.TriggerOnce() | Adds a OneTimeTrigger so the workflow runs exactly once. |
.TriggerPeriodic(interval, tolerance?) | Adds a TimedTrigger with the given interval and optional jitter. |
.TriggerOnSchedule(cronExpression, name?) | Adds a CronTrigger. Uses Quartz.NET cron syntax. |
.TriggerOnFileChange(path, filter?, name?) | Adds a FileTrigger watching the given directory. |
.AddTrigger(trigger) | Adds any pre-constructed IWorkflowTaskTriggerBase instance. |
.AddTrigger<TTrigger>(configure?) | Creates, optionally configures, and adds a typed trigger. |
.RemoveTrigger(trigger) | Removes a trigger from the workflow. |
FluentWorkflowBuilder – Task Shortcuts
The builder exposes the most common task operations directly. All of these delegate to the root StartTask and return a FluentWorkflowTaskBuilder scoped to the newly added task.
| Method | Description |
|---|---|
.Do<TTask>(configure?) | Adds a typed task as a child of the root. |
.Do(task) | Adds a pre-constructed task. |
.Print(text, color?, name?) | Adds a DebugOutputTask with a static string. |
.PrintExpression(expr, color?, name?) | Adds a DebugOutputTask whose message is a Roslyn expression. |
.SetVariable(varName, expression, name?) | Adds a SetVariableTask. |
.Set(varName, expression, name?) | Alias for SetVariable. |
.ReadFile(filePath, outputVar?, name?) | Adds a ReadFileTask with a static path. |
.ReadFileExpression(expr, outputVar?, name?) | Adds a ReadFileTask whose path is a Roslyn expression. |
.WriteFile(filePath, inputVar?, append?, name?) | Adds a WriteFileTask with a static path. |
.WriteFileExpression(expr, inputVar?, append?, name?) | Adds a WriteFileTask with a dynamic path. |
.Wait(duration, name?) | Adds a WaitTask. |
.If(expression, then, else?, name?) | Adds a runtime if/else branch (see below). |
.Switch(configure, name?) | Adds a multi-way switch (see below). |
.Loop(expression, body, name?) | Adds a LoopTask (see below). |
.ForEach(collectionExpression, body, elementVariableName?, name?) | Adds a ForEachTask iterating over an IEnumerable; the current item is exposed to the body via elementVariableName (or as the task output). |
.Async(name?, useThreadPool?) | Adds an AsyncTask scope. |
.Throttle(interval, body, persistenceId?, name?) | Adds a TimeThrottledScope. |
.OnChange(expression, body, persistenceId?, name?) | Adds a ChangeDetectedScope. |
FluentWorkflowTaskBuilder – Chaining
After adding a task you receive a FluentWorkflowTaskBuilder scoped to that task. Its API mirrors FluentWorkflowBuilder and adds:
| Method / Property | Description |
|---|---|
.Then | Property that returns the builder unchanged, used for readability (.Then.Print(…)). |
.Named(name) | Sets the name of the most recently added task. |
.WithOutput(varName) | Sets CustomOutputVariableName on the task. |
.WithInput(varName) | Sets CustomInputVariableName. |
.UseGlobalScopeForOutput() | Sets UseGlobalScopeForOutput = true. |
.UseGlobalScopeForInput() | Sets UseGlobalScopeForInput = true. |
.Retry(interval, maxRetries) | Enables retry with the given interval and count. |
.IgnoreErrors() | Sets ContinueOnError = true. |
.Parallel(params tasks[]) | Adds pre-built tasks as parallel branches. |
.AddBranchTask(task) | Adds a single parallel branch task. |
.Synchronize(name?) | Adds a MergeTask that waits for all preceding parallel branches (AND-gate). |
.Build() | Finalizes and returns the IWorkflow. |
.Persist() | Serializes the workflow to JSON and returns the string. |
Task ExecuteAsync() | Builds and immediately runs the workflow. |
Runtime Branching: If / Else
FluentWorkflow.Create("Branching Demo")
.TriggerOnce()
.Set("hour", "DateTime.Now.Hour")
.If("hour < 12",
then: t => t.Print("Good morning!"),
@else: e => e.Print("Good afternoon/evening!"),
name: "Time Check")
.Then.Print("Done.")
.Build();
Runtime Branching: Switch
FluentWorkflow.Create("Switch Demo")
.TriggerOnce()
.Set("score", "42")
.Switch(sw => sw
.Case("score >= 90", b => b.Print("Grade: A"))
.Case("score >= 70", b => b.Print("Grade: B"))
.Default(b => b.Print("Grade: F")),
"Grade Evaluation")
.Build();
Loops
FluentWorkflow.Create("Loop Demo")
.TriggerOnce()
.Set("counter", "0").UseGlobalScopeForOutput()
.Loop("counter < 5", body => body
.Set("counter", "counter + 1")
.UseGlobalScopeForInput()
.UseGlobalScopeForOutput()
.Then.PrintExpression("$\"Iteration {counter}\""))
.Then.Print("Done.")
.Build();
Parallel Branches and Merge
FluentWorkflow.Create("Parallel Demo")
.TriggerOnce()
.Do<StartTask>(t => t.Name = "Fan-Out")
.Parallel(
new ReadFileTask { FileName = "file1.txt", Name = "Read 1" },
new ReadFileTask { FileName = "file2.txt", Name = "Read 2" })
.Synchronize("Wait for all reads")
.Then.Print("All reads complete.")
.Build();
Extension Methods
The FluentWorkflowExtensions class adds higher-order helpers on top of FluentWorkflowTaskBuilder:
| Method | Description |
|---|---|
.Chain(params tasks[]) | Adds multiple pre-built tasks sequentially. Returns a builder scoped to the last task. |
.Repeat<TTask>(count, (task, index) => {}) | Adds count instances of a typed task sequentially, calling the configure callback for each. |
.ForEach<TTask, TItem>(items, (task, item) => {}) | Adds one typed task per item in the collection, configured with that item. |
.Parallel<TTask>(count, (task, index) => {}) | Adds count instances of a typed task as parallel branches. |
.Group(name, configure) | Wraps a set of tasks inside a named StartTask container. |
.Apply(configure) | Invokes an action on the builder and returns it, useful for extracting reusable configuration snippets. |
.When(condition, configure) | Applies the configure action only if condition is true at build time. |
.When(condition, whenTrue, whenFalse) | Build-time conditional with both branches. |
.DoIf<TTask>(condition, configure?) | Adds the task only if condition is true at build time. |
.When() and .DoIf() evaluate their condition when the workflow is being constructed, not when it executes. For runtime branching use .If() or .Switch().Persisting and Reloading
// Persist to JSON
string json = FluentWorkflow.Create("My Workflow")
.TriggerOnce()
.Print("Hello")
.Persist();
File.WriteAllText("my-workflow.awf", json);
// Reload and run
var workflow = FluentWorkflow.Load(File.ReadAllText("my-workflow.awf")).Build();
await workflow.StartAsync();