StepwiseBuilderGenerator 1.0.2
See the version list below for details.
dotnet add package StepwiseBuilderGenerator --version 1.0.2
NuGet\Install-Package StepwiseBuilderGenerator -Version 1.0.2
<PackageReference Include="StepwiseBuilderGenerator" Version="1.0.2" />
<PackageVersion Include="StepwiseBuilderGenerator" Version="1.0.2" />
<PackageReference Include="StepwiseBuilderGenerator" />
paket add StepwiseBuilderGenerator --version 1.0.2
#r "nuget: StepwiseBuilderGenerator, 1.0.2"
#:package StepwiseBuilderGenerator@1.0.2
#addin nuget:?package=StepwiseBuilderGenerator&version=1.0.2
#tool nuget:?package=StepwiseBuilderGenerator&version=1.0.2
Stepwise Builder Generator
This repository provides a Source Generator that creates strongly-typed, stepwise “fluent” builders for your types.
You simply annotate a class with [StepwiseBuilder] and specify the steps you need in the class’s parameterless
constructor. The source generator then produces a partial class containing builder interfaces and step methods.
Why Use Stepwise Builders?
- Compile-time safety: Each required step is enforced in sequence.
- Reduced boilerplate: No need to handwrite repetitive builder chains.
- Readable & maintainable: Clean, fluent APIs that guide users step-by-step.
How It Works
- Annotate a class with
[StepwiseBuilder]. - Inside the parameterless constructor, create a chain of methods using
GenerateStepwiseBuilder():AddStep<TArgument>(stepName, fieldName = null): adds a step to capture a value of typeTArgument.BranchFrom("BaseBuilderName", "BaseBuilderStep")(optional): indicates an alternate path is offered from the step beforeBaseBuilderStepinBaseBuilderName.CreateBuilderFor<TResult>(): defines the final target type being built.
When you compile, the generator inspects these calls and automatically produces:
- A partial builder class that implements interfaces representing each step.
- A chain of interfaces (e.g.,
IYourClassFirstStep,IYourClassSecondStep, …) to enforce the order of steps. - An optional extension method if you used
BranchFrom(...), allowing you to jump to a new step at the point * before* a specified step in another builder’s chain.
Quick Start Example
1. Create a Class & Decorate with [StepwiseBuilder]
using StepwiseBuilderGenerator;
[StepwiseBuilder]
public partial class MyClass
{
public MyClass() // Parameterless constructor
{
GenerateStepwiseBuilder()
.AddStep<int>("FirstStep", "MyIntField")
.AddStep<string>("SecondStep") // defaults to "SecondStepValue"
.AddStep<bool>("ThirdStep") // further step
.CreateBuilderFor<MyTargetType>();
}
}
When you build your project, the generator produces MyClass.g.cs in the same namespace, containing:
IMyClassFirstStepwith.FirstStep(int value).IMyClassSecondStepwith.SecondStep(string value).IMyClassThirdStepwith.ThirdStep(bool value).IMyClassBuildwith.Build(Func<MyClass, MyTargetType> buildFunc).- A partial
MyClassthat implements all the above interfaces, storing step values in fields likepublic int MyIntField;,public string SecondStepValue;, etc.
2. Using the Generated Builder
var builder = new MyClass();
MyTargetType result = builder
.FirstStep(42)
.SecondStep("Hello")
.ThirdStep(true)
.Build(instance =>
{
return new MyTargetType
{
SomeIntProperty = instance.MyIntField,
SomeStringProperty = instance.SecondStepValue,
SomeBoolProperty = instance.ThirdStepValue
};
});
The stepwise nature ensures you can’t skip or reorder steps; they must be called in the generated sequence.
3. Branching from Another Builder
Suppose we want an alternative path that branches before SecondStep. Here’s our original chain in MyClass:
FirstStep -> SecondStep -> ThirdStep -> Build
By writing:
[StepwiseBuilder]
public partial class MyOtherClass
{
public MyOtherClass()
{
GenerateStepwiseBuilder()
.BranchFrom("MyClass", "SecondStep") // offer a path from BEFORE 'SecondStep'
.AddStep<bool>("AlternateStep")
.CreateBuilderFor<AnotherType>();
}
}
We get:
- A partial
MyOtherClasswith steps for.AlternateStep(...). - An extension method so that right after
FirstStep(...)inMyClass, you can choose either to go.SecondStep(...) -> ThirdStep(...) -> Buildor.AlternateStep(...) -> Build. - Because it’s a separate path, once you choose
.AlternateStep(...), you cannot call.ThirdStep(...).
FAQ
1. What if I have generics in my class?
The generator handles generic type parameters by including them in the generated partial class and interfaces.
2. What if I have a branch in a generic class?
If you have a branch (BranchFrom(...)), the branching class should have a matching generic signature (names,
constraints, etc.) so the extension methods can properly link the two builders.
3. Can I add custom logic to steps?
Yes. Because the generated class is partial, you can add your own partial methods or fields. Steps themselves are
automatically generated as chainable methods.
4. What happens if I omit a step’s fieldName parameter?
The generator will default to naming that field as "{StepName}Value". For example, if your step
is .AddStep<int>("Foo"), the field becomes public int FooValue;.
5. Should I always write the build logic in .Build(...)?
Not necessarily. It’s often beneficial to keep the .Build(...) method minimal and place common or advanced build
logic in extension methods. For instance, suppose your generated interface is IMyClassBuild; you can do:
public static class MyClassBuilderExtensions
{
// This extension method extends the build interface directly
public static MyTargetType BuildMyTarget(this IMyClassBuild builder)
{
// Here, we call the underlying Build method, passing in your creation logic.
// You have direct access via the 'myClass' parameter in the delegate.
return builder.Build(myClass =>
{
return new MyTargetType
{
SomeIntProperty = myClass.MyIntField,
SomeStringProperty = myClass.SecondStepValue,
SomeBoolProperty = myClass.ThirdStepValue
};
});
}
}
Then in user code, you simply do:
var result = new MyClass()
.FirstStep(42)
.SecondStep("Hello")
.ThirdStep(true)
.BuildMyTarget();
This keeps your builder usage consistent while consolidating object-creation details elsewhere.
Steps Enum
Each generated builder class includes enum Steps listing all steps (excluding the final Build) in the order they
were declared. You might use this for logging, debugging, or reflection-based logic if desired.
Factory Methods in StepwiseBuilders
For each generated base builder, the generator also provides a static factory method within the StepwiseBuilders partial class. These methods allow you to conveniently initialize a builder without directly instantiating the generated partial class.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.CSharp (>= 4.3.0)
- Microsoft.CodeAnalysis.CSharp.Workspaces (>= 4.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.0 | 230 | 6/16/2025 |
| 3.0.0 | 342 | 5/14/2025 |
| 2.2.2 | 246 | 4/28/2025 |
| 2.2.1 | 160 | 4/26/2025 |
| 2.2.0 | 183 | 4/26/2025 |
| 2.1.3 | 168 | 4/25/2025 |
| 2.1.2 | 167 | 4/25/2025 |
| 2.1.1 | 181 | 4/25/2025 |
| 2.1.0 | 228 | 4/24/2025 |
| 2.0.2 | 226 | 4/24/2025 |
| 2.0.1 | 270 | 4/24/2025 |
| 2.0.0 | 230 | 4/23/2025 |
| 1.0.6 | 562 | 3/25/2025 |
| 1.0.5 | 545 | 3/25/2025 |
| 1.0.4 | 525 | 3/24/2025 |
| 1.0.3 | 173 | 1/13/2025 |
| 1.0.2 | 161 | 1/13/2025 |
| 1.0.1 | 169 | 1/9/2025 |
| 1.0.0 | 169 | 1/9/2025 |