{"id":13629585,"url":"https://github.com/StefH/FluentBuilder","last_synced_at":"2025-04-17T09:34:56.366Z","repository":{"id":37247955,"uuid":"387261449","full_name":"StefH/FluentBuilder","owner":"StefH","description":"A project which uses Source Generation to create a FluentBuilder for a specified model or DTO","archived":false,"fork":false,"pushed_at":"2024-10-27T08:38:01.000Z","size":398,"stargazers_count":170,"open_issues_count":5,"forks_count":15,"subscribers_count":8,"default_branch":"main","last_synced_at":"2024-10-29T18:46:23.633Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/StefH.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["StefH"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":"https://www.paypal.me/stefheyenrath"}},"created_at":"2021-07-18T20:15:29.000Z","updated_at":"2024-10-22T14:26:51.000Z","dependencies_parsed_at":"2023-02-09T21:40:19.568Z","dependency_job_id":"553ca90f-e7c1-4576-b27a-ddfffa67b7cc","html_url":"https://github.com/StefH/FluentBuilder","commit_stats":{"total_commits":152,"total_committers":5,"mean_commits":30.4,"dds":0.381578947368421,"last_synced_commit":"53096a8b54a1029532425bc727fdd831e9ed0092"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StefH%2FFluentBuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StefH%2FFluentBuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StefH%2FFluentBuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StefH%2FFluentBuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StefH","download_url":"https://codeload.github.com/StefH/FluentBuilder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223751253,"owners_count":17196595,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T22:01:14.240Z","updated_at":"2025-04-17T09:34:56.356Z","avatar_url":"https://github.com/StefH.png","language":"C#","readme":"# Projects\n\nSee also these blogs:\n- [mstack.nl - source-generators part 1](https://mstack.nl/blog/20210801-source-generators)\n- [mstack.nl - source-generators part 2](https://mstack.nl/blog/20220801-source-generators-part2/)\n- [mstack.nl - source-generators part 3](https://mstack.nl/blogs/source-generators-part3/)\n\n## CSharp.SourceGenerators.Extensions\nSee this [page](https://github.com/StefH/FluentBuilder/tree/main/src-extensions).\n\n## FluentBuilder\nA project which uses Source Generation to create a FluentBuilder for a specified model or DTO.\n\nThis project is based on [Tom Phan : \"auto-generate-builders-using-source-generator-in-net-5\"](https://justsimplycode.com/2020/12/06/auto-generate-builders-using-source-generator-in-net-5/).\n\n## NuGet\n[![NuGet Badge](https://shields.io/nuget/v/FluentBuilder)](https://www.nuget.org/packages/FluentBuilder)\n\n:memo: Note that FluentBuilder version 0.10.0 requires at least Visual Studio 17.11.5\n\n## :one: Usage on a existing class\n### Annotate a class\nAnnotate an existing class with `[FluentBuilder.AutoGenerateBuilder]` to indicate that a FluentBuilder should be generated for this class:\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder]\npublic class User\n{\n    public string FirstName { get; set; }\n\n    public string LastName { get; set; }\n\n    public DateTime? Date { get; set; }\n\n    [FluentBuilderIgnore] // Add this attribute to ignore this property when generating a FluentBuilder.\n    public int Age { get; set; }\n\n    public int Answer { get; set; } = 42; // When a default value is set, this value is also set as default in the FluentBuilder.\n}\n```\n\n#### AutoGenerateBuilder - attribute\n\nThis attribute has 4 arguments:\n- **type** (Type): The type for which to create the builder, see 'Define a class which needs to act as a builder'\n- **handleBaseClasses** (bool): Handle also base-classes. Default value is `true`.\n- **accessibility** (enum FluentBuilderAccessibility): Generate builder methods for `Public` or `PublicAndPrivate`. Default value when not provided is `Public`.\n- **methods** (enum  FluentBuilderMethods): Generate `With***` methods or also `Without***` methods. Default value when not provided is `WithOnly`. See also [Notes](#Notes)\n\n### Use FluentBuilder\n``` c#\nusing System;\nusing FluentBuilder;\n\nnamespace Test;\n\nclass Program\n{\n    static void Main(string[] args)\n    {\n        var user = new UserBuilder()\n            .WithFirstName(\"Test\")\n            .WithLastName(\"User\")\n            .Build();\n\n        Console.WriteLine($\"{user.FirstName} {user.LastName}\");\n    }\n}\n```\n\n### Use FluentBuilder when the class has a default (parameter-less) constructor\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder]\npublic class User\n{\n    public string FirstName { get; set; }\n\n    public string LastName { get; set; }\n\n    public DateTime? Date { get; set; }\n\n    public User()\n    {\n        FirstName = \"test\";\n    }\n}\n```\n\n``` c#\nusing System;\nusing FluentBuilder;\n\nnamespace Test;\n\nclass Program\n{\n    static void Main(string[] args)\n    {\n        var user = new UserBuilder()\n            .WithLastName(\"User\")\n            .Build(false); // ⭐ Provide `false` for `useObjectInitializer` here.\n\n        Console.WriteLine($\"{user.FirstName} {user.LastName}\");\n    }\n}\n```\n\n### Use FluentBuilder when the class has a constructor with parameters\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder]\npublic class User\n{\n    public string FirstName { get; set; }\n\n    public string LastName { get; set; }\n\n    public DateTime? Date { get; set; }\n\n    public User(string first)\n    {\n        FirstName = first;\n    }\n}\n```\n\n``` c#\nusing System;\nusing FluentBuilder;\n\nnamespace Test;\n\nclass Program\n{\n    static void Main(string[] args)\n    {\n        var user = new UserBuilder()\n            .UsingConstructor(\"First\")  // ⭐ Use `UsingConstructor` here.\n            .WithLastName(\"User\")\n            .Build();\n\n        Console.WriteLine($\"{user.FirstName} {user.LastName}\");\n    }\n}\n```\n\n### Using FluentBuilder when a class has an `Array` or `IEnumerable\u003cT\u003e` property\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder]\npublic class UserDto\n{\n    public IEnumerable\u003cEmailDto\u003e SecondaryEmails { get; set; }\n\n    public int[] IntArray { get; set; }\n}\n```\n\n``` c#\nvar user = new UserDtoBuilder()\n    .WithIntArray(ib =\u003e ib         // 👈 Use a Integer Array Builder\n        .Add(1)                    // Add a normal integer\n\n        .Add(() =\u003e 2)              // Add an integer with a Func\u003c\u003e\n        .Build()\n    )\n    .WithSecondaryEmails(sb =\u003e sb  // 👈 Use a EmailDto IEnumerable Builder\n        .Add(new EmailDto())       // Add a normal EmailDto using new() constructor\n\n        .Add(() =\u003e new EmailDto()) // Add an EmailDto using Func\u003c\u003e\n\n        .Add(eb =\u003e eb              // 👈 Use a EmailDto IEnumerable Builder to add an EmailDto\n            .WithPrimary(true)\n            .Build()\n        )\n        .Build()\n    )\n    .Build();\n```\n\n### Using FluentBuilder when a class has an `IDictionary\u003cTKey, TValue\u003e` property\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder]\npublic class UserDto\n{\n    public IDictionary\u003cstring, int\u003e Tags { get; set; }\n}\n```\n\n``` c#\nvar user = new UserDtoBuilder()\n    .WithTags(db =\u003e db      // 👈 Use a Dictionary\u003cTKey, TValue\u003e Builder\n        .Add(\"test\", 123)   // Add a key with value\n\n        .Add(() =\u003e new KeyValuePair\u003cstring, int\u003e(\"x\", 42)) // Add a KeyValuePair with a Func\u003c\u003e\n        .Build()\n    )\n    .Build();\n```\n\n## :two: Define a class which needs to act as a builder\nThis scenario is very usefull when you cannot modify the class to annotate it.\n\n### Create a public and partial builder class\nAnd annotate this class with `[AutoGenerateBuilder(typeof(XXX))]` where `XXX` is the type for which you want to generate a FluentBuilder.\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder(typeof(UserDto))]\npublic partial class MyUserDtoBuilder\n{\n}\n```\n\n#### ℹ️ Generic Attribute\nIf you are using **C# 11.0** (`.NET 7` and up), you can also use the generic `AutoGenerateBuilder\u003cT\u003e`-attribute.\nExample:\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder\u003cUserDto\u003e()]\npublic partial class MyUserDtoBuilder\n{\n}\n```\n\n\n### Use FluentBuilder\n``` c#\nusing System;\nusing FluentBuilder;\n\nnamespace Test;\n\nclass Program\n{\n    static void Main(string[] args)\n    {\n        var user = new MyUserDtoBuilder() // 👈 Just use your own Builder\n            .WithFirstName(\"Test\")\n            .WithLastName(\"User\")\n            .Build();\n\n        Console.WriteLine($\"{user.FirstName} {user.LastName}\");\n    }\n}\n```\n\n## Extension Method\n\nBy default, the `AsBuilder` extension method is also generated which allows you to change an existing instance using the `With`-methods from the builder.\n\nExample:\n``` c#\nvar user = await dbContext.Users.FirstAsync();\n\nuser = user.AsBuilder() // Lifts the user into a builder instance\n    .WithLastName(\"Different LastName\") // Updates \"LastName\" while keeping existing properties\n    .Build(); // Changes are applied\n\nawait dbContext.SaveChangesAsync(); // User's LastName property is updated.\n```\n\n## Notes\n\nSince version 0.8.0, this FluentBuilder will only generate the `With***` methods. If you want the builder to also generate the `Without***` methods, add the enum `FluentBuilderMethods.WithAndWithout` to the attribute.\n\n``` c#\nusing FluentBuilder;\n\n[AutoGenerateBuilder(typeof(UserDto), FluentBuilderMethods.WithAndWithout)]\npublic partial class MyUserDtoBuilder\n{\n}\n```\n\n# Links\n- https://protogen.marcgravell.com/\n- https://protobuf-decoder.netlify.app/\n- https://www.protobufpal.com/\n","funding_links":["https://github.com/sponsors/StefH","https://www.paypal.me/stefheyenrath"],"categories":["Source Generators","Do not want to test 112 ( old ISourceGenerator )"],"sub_categories":["Patterns","1. [ThisAssembly](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly) , in the [EnhancementProject](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enhancementproject) category"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FStefH%2FFluentBuilder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FStefH%2FFluentBuilder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FStefH%2FFluentBuilder/lists"}