RSCG – IncrementalSourceGenerator.BuilderPattern

 
 

name IncrementalSourceGenerator.BuilderPattern
nuget https://www.nuget.org/packages/IncrementalSourceGenerator.BuilderPattern/
link https://github.com/MartinBarrettNielsen11/Incremental-source-generator-builder-pattern
author Martin Barrett Nielsen

Generate builder pattern code for classes with many properties

 

This is how you can use IncrementalSourceGenerator.BuilderPattern .

The code that you start with is


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


The code that you will use is


using Builder;

Console.WriteLine("create person builder");

var p = new PersonBuilder()
    .WithFirstName("Andrei")
    .WithLastName("Ignat")
    .Build();
    


Console.WriteLine(p.FullName());



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}";
}

 

The code that is generated is

#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

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/IncrementalSourceGenerator.BuilderPattern


Posted

in

,

by

Tags: