Skip to main content

DimonSmart.BuilderGenerator by Dmitry Dorogoy

NuGet / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: DimonSmart.BuilderGenerator

Generate builder classes via source generation. Simplifies object creation with Builder pattern.

Author: Dmitry Dorogoy

NuGet: https://www.nuget.org/packages/DimonSmart.BuilderGenerator/

You can find more details at https://github.com/DimonSmart/BuilderGenerator

Source: https://github.com/DimonSmart/BuilderGenerator

Original Readme

note

BuilderGenerator

BuilderGenerator is a Roslyn Source Generator that creates Builder classes at compile time. It�s especially helpful for classes with many properties, giving you a clear, explicit way to see what�s being initialized. You can even generate builders for third-party classes, and a simple hierarchy is supported, including links from child objects back to their parent. If you need something more specialized, take the generated code and adapt it to fit your own needs.


Installation

Install via NuGet:

dotnet add package BuilderGenerator

Or use your preferred IDE�s NuGet package manager interface.


How It Works

The BuilderGenerator uses two main approaches to specify which class to generate a builder for:

  1. Attribute directly on the class.
  2. Attribute on a �container� class where you specify TargetType in [GenerateBuilder(TargetType = typeof(YourClass))].

Below are some examples.


Examples

1. Simple Scenario: Attribute on the Class

In this example, we have a Person class and an Address class. We annotate them directly:

csharp
using BuilderGenerator.Runtime;

namespace BuilderGenerator.Sample
{
public interface IPerson
{ }

[GenerateBuilder] // Directly on the Person class
public class Person : IPerson
{
public string? Name { get; set; }
public int Age { get; set; }
public Address? Address { get; set; }
}

[GenerateBuilder] // Directly on the Address class
public class Address
{
public string? Street { get; set; }
public string? City { get; set; }
public IPerson? Person { get; set; }
}
}

Thanks to these attributes, the Source Generator will create:

  • PersonBuilder (with fluent methods Name(...), Age(...), Address(...))
  • AddressBuilder (with fluent methods Street(...), City(...), Person(...))

Usage might look like:

csharp
var person = PersonBuilder.Create()
.Name("John")
.Age(30)
// Here we invoke a nested Address builder
.Address(addr => addr
.Street("Main St.")
.City("Metropolis")
)
.Build();

After building, person becomes an instance of the Person class populated with those property values.


2. Container Approach: Attribute on Another Class

Sometimes you might not want to mark the target class directly with [GenerateBuilder].
Instead, you can create a separate "container" class (or file) and specify which type it should generate a builder for:

csharp
using BuilderGenerator.Runtime;

namespace BuilderGenerator.OtherSamples
{
[GenerateBuilder(TargetType = typeof(Person))]
[GenerateBuilder(TargetType = typeof(Address))]
public class PersonBuilderContainer
{
// Could be empty
}

// Meanwhile, Person and Address themselves have no direct attribute:
public class Person
{
public string? Name { get; set; }
public int Age { get; set; }
public Address? Address { get; set; }
}

public class Address
{
public string? Street { get; set; }
public string? City { get; set; }
public IPerson? Person { get; set; }
}
}

The generator will now produce PersonBuilderContainerBuilder.g.cs and AddressBuilderContainerBuilder.g.cs (or very similarly named files) that act as your fluent builder classes.

Usage is the same pattern:

csharp
var person = PersonBuilderContainer.Create()
.Name("Alice")
.Age(25)
.Address(addr => addr
.Street("Baker St.")
.City("London")
)
.Build();

3. Hierarchical Builder Example

The above code already shows how you can nest calls, for example:

csharp
var person = PersonBuilder.Create()
.Name("Bruce")
.Age(42)
.Address(a => a
.Street("Gotham Rd.")
.City("Gotham")
)
.Build();

When Address(...) is called, the generator automatically creates a nested builder for Address.


4. Setting a Reference to the Parent

In some scenarios, you may want an object to reference its �parent.� For instance, an Address might have a property Person Person { get; set; }. In your example, IPerson? Person { get; set; } is a reference back to the parent. The Source Generator includes a helper method called:

csharp
public TParent BuildAndSetParent<TProperty>(
Expression<Func<TheChildClass, TProperty>> parentSelector
) where TProperty : class
{
// ...
}

This method allows you to set the parent reference in the child builder. Here�s a conceptual usage snippet (the code is somewhat simplified to illustrate the idea):

csharp
var personBuilder = PersonBuilder.Create();
var addressBuilder = AddressBuilder.Create();

// Suppose you want address.Person to be the person you are building
// and want the final personBuilder to keep track of the newly built Address:

addressBuilder
.Street("Parent Av.")
.City("Capital City")
.BuildAndSetParent(a => a.Person);
// "a => a.Person" indicates that the child Person property should refer back to the parent

License

0BSD License:
You�re free to use, copy, modify, distribute, and do pretty much anything else with BuilderGenerator.
See the 0BSD text for details.


Contributing

If you encounter bugs or have feature requests, feel free to open an issue or submit a pull request on GitHub.


About

note

Generating builder pattern code for classes

How to use

Example (source csproj, source files)

This is the CSharp Project that references DimonSmart.BuilderGenerator

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DimonSmart.BuilderGenerator" Version="1.25310.2229" />
</ItemGroup>


</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX


using System;
namespace DimonSmart.BuilderGenerator.Runtime
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class GenerateBuilderAttribute : Attribute
{
public Type TargetType { get; set; }
}
}

Useful

Download Example (.NET C# )

Share DimonSmart.BuilderGenerator

https://ignatandrei.github.io/RSCG_Examples/v2/docs/DimonSmart.BuilderGenerator

In the same category (Builder) - 5 other generators

Architect.DomainModeling

BuilderGenerator

Fluentify

Hsu.Sg.FluentMember

StepwiseBuilderGenerator