IncrementalSourceGenerator.BuilderPattern by Martin Barrett Nielsen
NuGet / site data
Details
Info
Name: IncrementalSourceGenerator.BuilderPattern
Incremental source generator that that reduces boilerplate in test object builders by generating the repetitive structure, while enabling developers to focus on the more meaningful, hand-crafted logic via partial classes
Author: Martin Barrett Nielsen
NuGet: https://www.nuget.org/packages/IncrementalSourceGenerator.BuilderPattern/
You can find more details at https://github.com/MartinBarrettNielsen11/Incremental-source-generator-builder-pattern
Source: https://github.com/MartinBarrettNielsen11/Incremental-source-generator-builder-pattern
Author
Martin Barrett Nielsen

Original Readme
About
Generate builder pattern code for classes with many properties
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
- Person.cs
This is the CSharp Project that references IncrementalSourceGenerator.BuilderPattern
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IncrementalSourceGenerator.BuilderPattern" Version="1.0.2" />
</ItemGroup>
</Project>
This is the use of IncrementalSourceGenerator.BuilderPattern in Program.cs
using Builder;
Console.WriteLine("create person builder");
var p = new PersonBuilder()
.WithFirstName("Andrei")
.WithLastName("Ignat")
.Build();
Console.WriteLine(p.FullName());
This is the use of IncrementalSourceGenerator.BuilderPattern in Person.cs
using Generator;
namespace Builder;
[Builder(typeof(Person))]
public partial class PersonBuilder
{
}
public class Person
{
public string FirstName \{ get; set; }
public string LastName \{ get; set; }
public string FullName() => $"{FirstName} {LastName}";
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- BuilderAttribute.g.cs
- Builder_Person.g.cs
- Builder_PersonBuilder.g.cs
- DomainAssertionExtensions.g.cs
#nullable enable
#pragma warning disable CA1813, CA1019, IDE0065, IDE0034, IDE0055
using System;
namespace Generator;
[System.CodeDom.Compiler.GeneratedCode("Generator", "v1")]
[AttributeUsage(AttributeTargets.Class)]
public sealed class BuilderAttribute(Type type) : Attribute
{
public Type TargetType \{ get; \} = type;
}
#pragma warning restore CA1813, CA1019, IDE0065, IDE0034, IDE0055
#nullable enable
#pragma warning disable IDE0055, IDE0008
using System;
using System.Linq;
using System.Collections.Generic;
using Generator;
namespace Builder;
[System.CodeDom.Compiler.GeneratedCode("Generator", "v1")]
public partial class Person
{
private Func<Builder.PersonBuilder> _factory = () => new();
private readonly List<Action<Builder.PersonBuilder>> _domainRules = new();
/// <summary>
/// Returns configured instance of Builder.PersonBuilder
/// </summary>
public Builder.PersonBuilder Build()
{
Builder.PersonBuilder instance = _factory();
_domainRules.ForEach(action => action(instance));
return instance;
}
}
#pragma warning restore IDE0055, IDE0008
#nullable enable
#pragma warning disable IDE0055, IDE0008
using System;
using System.Linq;
using System.Collections.Generic;
using Generator;
namespace Builder;
[System.CodeDom.Compiler.GeneratedCode("Generator", "v1")]
public partial class PersonBuilder
{
private Func<Builder.Person> _factory = () => new();
private readonly List<Action<Builder.Person>> _domainRules = new();
private Func<string>? _firstName;
private Func<string>? _lastName;
public PersonBuilder WithFirstName(string @firstName)
{
return WithFirstName(() => @firstName);
}
public PersonBuilder WithFirstName(Func<string> @firstName)
{
_firstName = @firstName;
return this;
}
public PersonBuilder WithLastName(string @lastName)
{
return WithLastName(() => @lastName);
}
public PersonBuilder WithLastName(Func<string> @lastName)
{
_lastName = @lastName;
return this;
}
/// <summary>
/// Returns configured instance of Builder.Person
/// </summary>
public Builder.Person Build()
{
Builder.Person instance = _factory();
if(_firstName is not null)
instance.FirstName = _firstName.Invoke();
if(_lastName is not null)
instance.LastName = _lastName.Invoke();
_domainRules.ForEach(action => action(instance));
return instance;
}
}
#pragma warning restore IDE0055, IDE0008
#pragma warning disable IDE0055, IDE0008
#nullable enable
using System;
using System.Collections.Generic;
namespace Generator;
[System.CodeDom.Compiler.GeneratedCode("Generator", "v1")]
public static class DomainAssertionExtensions
{
/// <summary>
/// Adds a domain validation rule to be executed during the build phase.
/// </summary>
/// <param name="_domainRules">The list of post-build domain rules.</param>
/// <param name="predicate">A function that returns true when the entity violates a rule.</param>
/// <param name="errorMessage">The error message that will be thrown if the rule fails.</param>
public static void AddDomainRule<TEntity>(
this List<Action<TEntity>> _domainRules,
Func<TEntity, bool> predicate,
string errorMessage)
{
_domainRules.Add(e =>
{
if (predicate(e))
throw new InvalidOperationException(errorMessage);
});
}
}
#pragma warning restore IDE0055, IDE0008
Useful
Download Example (.NET C#)
Share IncrementalSourceGenerator.BuilderPattern
https://ignatandrei.github.io/RSCG_Examples/v2/docs/IncrementalSourceGenerator.BuilderPattern
Category "Builder" has the following generators:
1 Architect.DomainModeling
2024-03-02
2 BuilderGenerator
2023-10-04
3 DimonSmart.BuilderGenerator
2025-07-03
4 Fluentify
2024-08-02
5 Hsu.Sg.FluentMember
2024-11-08
6 IncrementalSourceGenerator.BuilderPattern
2026-08-23
7 OrderedBuildersGenerator
2025-12-18
8 ShadowWriterBuilder
2025-07-24
9 StepwiseBuilderGenerator
2025-03-23
10 TypedStateBuilder.Generator
2026-05-16