<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Guillaume Faas</title>
    <description>The latest articles on DEV Community by Guillaume Faas (@tr00d).</description>
    <link>https://dev.to/tr00d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F981891%2F2064afc8-4d2a-46d9-9523-9f5756b14169.jpeg</url>
      <title>DEV Community: Guillaume Faas</title>
      <link>https://dev.to/tr00d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tr00d"/>
    <language>en</language>
    <item>
      <title>Supabase .NET DevLog #9</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Tue, 08 Sep 2026 14:59:51 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-9-21h9</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-9-21h9</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK 🎉&lt;/p&gt;

&lt;p&gt;Here we are, it finally happened: &lt;strong&gt;v8.0.0 has been published&lt;/strong&gt;, and is now available!&lt;br&gt;
Well, technically... v8.1.0 is the latest version now, as I've pushed a couple of features too.&lt;/p&gt;

&lt;p&gt;This is an important milestone for the SDK and, with the major version behind us now, we'll get back to a much faster pace of releases.&lt;br&gt;
I see it's being picked up by the community already, so please share your feedbacks!&lt;/p&gt;

&lt;p&gt;So, if you want to see what's been packed in v8.0.0, here's the &lt;a href="https://github.com/supabase-community/supabase-csharp/releases/tag/v8.0.0" rel="noopener noreferrer"&gt;changelog&lt;/a&gt;.&lt;br&gt;
If you're considering upgrading (you definitely should!), here's our &lt;a href="https://github.com/supabase-community/supabase-csharp/blob/master/docs/migrations/v8.0.0.md" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt;. It's not a changelog: it lists all the breaking changes you might encounter during the upgrade, and how to address them.&lt;/p&gt;

&lt;p&gt;I'm currently a bit away from the SDK itself, as I'm focused on content for now. Docs need to get updated, I'm writing a blog post to promote that version, as well as an introduction/tutorial post for the SDK as a whole.&lt;br&gt;
TLDR: more writing for me!&lt;/p&gt;

&lt;p&gt;And if you have any questions, you know where to ask.&lt;/p&gt;

&lt;p&gt;Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #8</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Tue, 01 Sep 2026 13:58:44 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-8-49mk</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-8-49mk</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK 🎉&lt;/p&gt;

&lt;p&gt;In last week's post, I mentioned I was attending a conference in Germany.&lt;/p&gt;

&lt;p&gt;So...&lt;/p&gt;

&lt;p&gt;I went to Gamescom in Cologne! Let me tell you, it was straight up insane... I've been to a lot of conferences in the last 4 years (around 50 events total) and I've never seen anything like it.&lt;/p&gt;

&lt;p&gt;Anyway, I went there to meet indie developers and see how Supabase fits in that space. It was a fantastic experience, the community is very open and I was lucky enough to meet a studio (&lt;a href="https://lootdonkey.itch.io" rel="noopener noreferrer"&gt;Loot Donkey&lt;/a&gt;) which &lt;strong&gt;showcased a game built with Supabase&lt;/strong&gt;. The game's called &lt;a href="https://store.steampowered.com/app/4380860/Fool_King/" rel="noopener noreferrer"&gt;Fool King&lt;/a&gt;; feel free to check them out!&lt;/p&gt;

&lt;p&gt;Back to our SDK, each day brings us closer to the release of v8.0.0... which will happen &lt;strong&gt;this week&lt;/strong&gt;!&lt;br&gt;
I've integrated a couple of new features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full HTTP rework, enabling a better customization and override of the internal HTTP client&lt;/li&gt;
&lt;li&gt;A new extension for dependency injection in ASP.NET&lt;/li&gt;
&lt;li&gt;Support for publishable and secret keys&lt;/li&gt;
&lt;li&gt;Automation on the quality gate (auto format, auto baseline update)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll try to fit a couple of more features before the release (best effort). If you want more details about what will get released, have a look &lt;a href="https://github.com/supabase-community/supabase-csharp/pull/343" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;lately, I'd like to thank recurring contributors Bruno (&lt;a href="https://github.com/fresh55" rel="noopener noreferrer"&gt;@fresh55&lt;/a&gt;) and Diego (&lt;a href="https://github.com/diegofesanto" rel="noopener noreferrer"&gt;@diegofesanto&lt;/a&gt;) for their help with the SDK. Much appreciated!&lt;/p&gt;

&lt;p&gt;Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #7</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Tue, 25 Aug 2026 16:21:05 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-7-4gjb</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-7-4gjb</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK 🎉&lt;/p&gt;

&lt;p&gt;Last week, I continued tweaking the quality gate, especially regarding code coverage. I faced a nasty problem where coverage would sometimes differ when run locally vs. in a GitHub Workflow with async tasks. This creates a major problem when we expect the new coverage to be equal or higher... The good news if I solved it.&lt;/p&gt;

&lt;p&gt;Anyway, I also added some QoL there too. Now, the baseline is automatically refreshed after a push on master, and style/format/naming guidelines aren't enforced anymore on a Pull Request. This step is now only a signal, because another workflow runs &lt;code&gt;dotnet format&lt;/code&gt; on updated files after a push on master. &lt;br&gt;
TLDR: &lt;strong&gt;less friction for contributors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The major improvement has been the HTTP rework. Several developers complained (for good reasons) that there was no way to override the internal HTTP client used by the SDK, either for testing purposes or to define different options (connection pools, retry policies, etc). This had to be done across the board, and will be released along with v8.0.0 🎉&lt;/p&gt;

&lt;p&gt;Finally, we're getting an increased flow of contributions and that's just fantastic to see 🙂&lt;/p&gt;

&lt;p&gt;This week will be a bit quiet, as I'm attending a gaming conference in Germany. No spoilers, I'll share more next week 😉&lt;/p&gt;

&lt;p&gt;Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #6</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Tue, 18 Aug 2026 04:55:06 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-6-40b2</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-6-40b2</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK 🎉&lt;/p&gt;

&lt;p&gt;Following the monorepo migration, I started working towards the new major v8.0.0:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upgraded all packaged to &lt;code&gt;netstandard2.1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enabled lockstep versioning to v8.0.0&lt;/li&gt;
&lt;li&gt;Reworked the full package management, to guarantee uniform dependencies&lt;/li&gt;
&lt;li&gt;Broader improvements on code styling, GitHub Actions, and repository structure&lt;/li&gt;
&lt;li&gt;Migrated from Newtonsoft.Json to System.Text.Json for all packages&lt;/li&gt;
&lt;li&gt;Started writing a proper &lt;a href="https://github.com/supabase-community/supabase-csharp/blob/master/docs/migrations/v8.0.0.md" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt; for v8.0.0 (WIP)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to stay tuned with what's coming in v8.0.0, have a look at &lt;a href="https://github.com/supabase-community/supabase-csharp/pull/343" rel="noopener noreferrer"&gt;this PR&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Priori to the System.Text.Json migration, I implemented a full suite of approval tests to guarantee that serialization didn't change. The codebase didn't have any, and we can't tackle such a migration without a safety net. If you wonder what Approval Testing is, just le me know. TLDR: Tests create a snapshot, and they keep getting evaluated against that snapshot. It guarantees models and queries keep producing the same output 😉&lt;/p&gt;

&lt;p&gt;On top of all that, I created a proper quality gate for the SDK. It is executed by GitHub Actions and potentially local agents. As it's a script, it is &lt;strong&gt;deterministic&lt;/strong&gt;! 🎉&lt;br&gt;
It guarantees that things do not get worse (aka. stay stale or get better):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All tests (Unit/Contract, Approval, E2E)&lt;/li&gt;
&lt;li&gt;Modified code must comply with format/style/naming guidelines specified in &lt;code&gt;.editorconfig&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Number of warnings cannot increase (goal is to get to zero and enable &lt;code&gt;TreatWarningsAsErrors&lt;/code&gt; solution-wide)&lt;/li&gt;
&lt;li&gt;No vulnerabilities on dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From now on, this will be a &lt;strong&gt;hard requirement&lt;/strong&gt; for all contributions, including mine. You can picture this as enforcing the "boyscout rule" to the whole codebase.&lt;/p&gt;

&lt;p&gt;Stay tuned for more.&lt;br&gt;
Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #5</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Mon, 10 Aug 2026 14:37:07 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-5-2go1</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-5-2go1</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK! 🎉&lt;/p&gt;

&lt;p&gt;Last week marks a milestone for the SDK: the migration to a monorepo is now &lt;strong&gt;done&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Achievement Unlocked&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Everything can be found under the main repository &lt;a href="https://github.com/supabase-community/supabase-csharp" rel="noopener noreferrer"&gt;supabase-csharp&lt;/a&gt;. Every package has its own project under &lt;code&gt;packages/&lt;/code&gt;. &lt;br&gt;
Nothing changes for you (&lt;strong&gt;yet&lt;/strong&gt;): same packages, same public API.&lt;/p&gt;

&lt;p&gt;Prior to that, I had to merge/fix all the open PRs for every package, as these couldn't get carried over, and transferred all the open issues too. &lt;/p&gt;

&lt;p&gt;This is now the single place to contribute and fill issues, as other repositories have been archived. &lt;/p&gt;

&lt;p&gt;Now that this has been dealt with, I'm focusing on the upcoming v8.0.0 and all the breaking changes that come with it. Wish me luck! 😅&lt;/p&gt;

&lt;p&gt;Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #4</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Mon, 03 Aug 2026 13:36:31 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-4-534a</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-4-534a</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK! 🎉&lt;/p&gt;

&lt;p&gt;I briefly mentioned I was working on the test suite in our previous entry. Well, I've got great news! &lt;br&gt;
I made substantial progress on that: a small bump in code coverage (&lt;strong&gt;+11%&lt;/strong&gt; average across packages), but mostly a significant bump on mutation score (&lt;strong&gt;+41%&lt;/strong&gt; average across packages). If you never heard about mutation testing, the &lt;em&gt;tldr&lt;/em&gt; is it represents how much you can trust your test suite, with a number: the &lt;strong&gt;mutation score&lt;/strong&gt;. I digress, but let me know if you want to hear more about that.&lt;br&gt;
This will help me build momentum on the SDK moving forward.&lt;/p&gt;

&lt;p&gt;I also updated our &lt;a href="https://supabase.com/docs/reference/csharp/start" rel="noopener noreferrer"&gt;SDK Reference&lt;/a&gt;, which hasn't been updated for more than two years, and made sure we exposed a C# snippet for every product in our docs. &lt;br&gt;
The only caveat is nothing is automated on that front... I'll tackle that when we reach the monorepo.&lt;/p&gt;

&lt;p&gt;Aside from those updates, I also closed a couple of PRs from contributors, and published a couple of releases. &lt;br&gt;
I have to say the community have been responding so positively so far, it's just awesome 😎&lt;/p&gt;

&lt;p&gt;We're getting closer to the monorepo migration. I'm currently planning this and getting together with other teams. My goal is to land this in the first half of August, and then the priority will be to work towards the new major version (hopefully soon).&lt;/p&gt;

&lt;p&gt;Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>opensource</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #3</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Mon, 27 Jul 2026 12:29:46 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-3-442p</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-3-442p</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK! 🎉&lt;/p&gt;

&lt;p&gt;Last week, I closed all the remaining critical fixes (P0s), which represented a total of 16 GitHub issues affecting developers.&lt;/p&gt;

&lt;p&gt;Aside from the usual fixes, I also shipped OpenTelemetry which is a huge step forward for the SDK's transparency compared to the old debug logging.&lt;/p&gt;

&lt;p&gt;We also got more releases this week as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supabase v1.4.0&lt;/li&gt;
&lt;li&gt;Supabase.Functions v2.2.0&lt;/li&gt;
&lt;li&gt;Supabase.Gotrue v6.2.0&lt;/li&gt;
&lt;li&gt;Supabase.Postgrest v4.4.0&lt;/li&gt;
&lt;li&gt;Supabase.Realtime v7.3.0&lt;/li&gt;
&lt;li&gt;Supabase.Storage v2.5.0&lt;/li&gt;
&lt;li&gt;Supabase.Core v1.2.0&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember folks: &lt;strong&gt;always keep your dependencies up-to-date&lt;/strong&gt;, just sayin'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the team, we also discussed the new versioning structure once we move to a monorepo: &lt;strong&gt;lockstep versioning&lt;/strong&gt;, meaning all packages share the same version number.&lt;br&gt;
One caveat is we'll have to start fresh at v8.0.0, so a +7 bump on the main package because of the odd version distribution we currently have. This will give us an opportunity to ship breaking changes at the same time to improve the DevEx.&lt;/p&gt;

&lt;p&gt;I'm currently working on improving the overall test-suite, and I'll probably share metrics about that next week. This is a mandatory step for the SDK's future: we (the community, me included) need a test-suite we can trust, otherwise we can't safely add/update features.&lt;/p&gt;

&lt;p&gt;This is probably the last step before the monorepo's transition.&lt;/p&gt;

&lt;p&gt;Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>opensource</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #2</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Mon, 20 Jul 2026 06:00:37 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-2-22e7</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-2-22e7</guid>
      <description>&lt;p&gt;Welcome to our weekly log for the Supabase .NET SDK! 🎉&lt;/p&gt;

&lt;p&gt;Last week, I continued building our momentum on improving the overall experience with the SDK.&lt;br&gt;
I released other critical fixes, as well as some improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;[Global] Fixing automated releases&lt;/strong&gt;: The release process wasn't uniform across packages, and was also broken at places (especially on the umbrella package). &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Global] Fixed the telemetry&lt;/strong&gt;: The telemetry is now consistent across packages but also more detailed. This will give us more details about who our users are and how they use our products. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Global] Make Newtonsoft.Json 13.0.2 the ground version&lt;/strong&gt;: We had to reduce the ground version of this dependency because of Unity 6 LTS. Indeed, Unity 6 ships with 13.0.2 and that version can't be bumped. This was locking out customers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[GoTrue] Add missing OAuth2 &lt;code&gt;state&lt;/code&gt;&lt;/strong&gt;: We exposed a server-side &lt;code&gt;state&lt;/code&gt; value, strengthening CSRF protection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Postgrest] Reference fields incorrectly included in UPDATE and DELETE queries&lt;/strong&gt;: The behavior was only correct for INSERT, but failing for others. All we had to do was to cover &lt;code&gt;Patch&lt;/code&gt; and &lt;code&gt;Delete&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Postgrest] Fixed enums serialised as integers&lt;/strong&gt;: To avoid breaking existing data, this is something users must opt-in with &lt;code&gt;ClientOptions.SerializeEnumsAsStrings&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also did a lot of triage on all the repositories. Between the fixes/improvements and clearing outdated issues, 14 issues were solved/removed.&lt;/p&gt;

&lt;p&gt;And all of this is now accessible for customers! 🎉 I published new versions for our entire SDK suite, the first one since a little while (addressing the dependency issues we mentioned in the previous post):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supabase &lt;strong&gt;v1.2.0&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Supabase.Functions &lt;strong&gt;v2.1.1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Supabase.Gotrue &lt;strong&gt;v6.1.0&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Supabase.Postgrest &lt;strong&gt;v4.2.0&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Supabase.Realtime &lt;strong&gt;v7.2.1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Supabase.Storage &lt;strong&gt;v2.4.2&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Supabase.Core &lt;strong&gt;v1.1.0&lt;/strong&gt;
That being said, the current release process is quite painful. I can't wait to move to a monorepo, with a single &lt;code&gt;Release&lt;/code&gt; button 😅 It's a mandatory move if I want to speed up the pace of releases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This week will follow the same trajectory: fixing existing issues, release them to customers, and keep sanitizing repositories before moving towards a monorepo.&lt;/p&gt;

&lt;p&gt;Have a a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>opensource</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #1</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Mon, 13 Jul 2026 07:07:26 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-1-1g2e</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-1-1g2e</guid>
      <description>&lt;p&gt;Welcome to the first entry of our weekly log for the Supabase .NET SDK! 🎉&lt;/p&gt;

&lt;p&gt;Being still a new joiner in the company, I' still ramping up. I've been working on a plan to set up the direction of the SDK and prioritise what needs to be done first. I'm far from my full velocity, but there's a lot to catch up on.&lt;/p&gt;

&lt;p&gt;I started with critical fixes, as the SDK was broken in some places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;[GoTrue] Auth kept dead sessions alive&lt;/strong&gt;: when a refresh token got rejected, the client only cleared the session in one specific case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[GoTrue] Email OTP sign-in and password reset were broken:&lt;/strong&gt; &lt;code&gt;SignInWithOtp&lt;/code&gt; and &lt;code&gt;ResetPasswordForEmail&lt;/code&gt; had the PKCE verifier and challenge swapped (the SHA-256 hash was sent as the raw value, and vice-versa).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[PostgREST] Negation dropped in predicates:&lt;/strong&gt; a silent issue where conditions like &lt;code&gt;x =&amp;gt; !(x.Name == "foo")&lt;/code&gt; were dropping the negation on &lt;code&gt;Where&lt;/code&gt;, &lt;code&gt;Update&lt;/code&gt;, and &lt;code&gt;Delete&lt;/code&gt;.
*** [PostgREST] Truncated DateTime:** reading dropped sub-second precision and UTC offset. Any round-trip was failing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[PostgREST] Where improvements&lt;/strong&gt;: &lt;code&gt;ids.Contains(x.Id)&lt;/code&gt; now translates into an &lt;code&gt;in&lt;/code&gt; filter rather than throwing, boolean columns (ex: &lt;code&gt;x.IsActive&lt;/code&gt;) can be used directly, and comparing two columns to each other throws a clear error explaining why PostgREST can't do that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's worth to note that all of these changes are yet unreleased.&lt;/p&gt;

&lt;p&gt;I will ship more critical fixes, and an improvement on the SDK's telemetry, before releasing a clean version this week. This will be a good opportunity to align dependencies, as the SDK doesn't reference all the latest versions of its sub-packages at the moment.&lt;/p&gt;

&lt;p&gt;Once we stabilize the usage, the first milestone will be to migrate to a monorepo. Hopefully, soon.&lt;/p&gt;

&lt;p&gt;Have a great day, and keep coding!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>opensource</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Supabase .NET DevLog #0</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Thu, 09 Jul 2026 11:50:56 +0000</pubDate>
      <link>https://dev.to/tr00d/supabase-net-devlog-0-1ofd</link>
      <guid>https://dev.to/tr00d/supabase-net-devlog-0-1ofd</guid>
      <description>&lt;p&gt;&lt;em&gt;Quick context if you haven't seen the latest news&lt;/em&gt;: I recently joined &lt;a href="https://supabase.com" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; as &lt;strong&gt;.NET SDK Engineer&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxz1f83iy9s6djnwe7k4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxz1f83iy9s6djnwe7k4e.png" alt="Supabase Logo Dark" width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Their &lt;a href="https://github.com/supabase-community/supabase-csharp" rel="noopener noreferrer"&gt;.NET SDK&lt;/a&gt; is moving from community maintenance to official support, and I'm the main contributor moving forward 🎉&lt;/p&gt;

&lt;p&gt;Especially with SDKs, I've always liked being engaged with developers: keeping them in the loop, but also collecting feedback.&lt;/p&gt;

&lt;p&gt;So, I'm starting a &lt;strong&gt;weekly log&lt;/strong&gt;! &lt;/p&gt;

&lt;p&gt;Every week, I'll publish a short post about what happened on the SDK and where it's heading. Nothing fancy: just a few bullet points, some context when a decision deserves an explanation. That's it.&lt;/p&gt;

&lt;p&gt;Fair warning: what I plan for a week &lt;strong&gt;won't always get delivered&lt;/strong&gt;... because Life happens. Priorities move, issues show up, unexpected stuff, etc. So, don't take the plan for a promise.&lt;/p&gt;

&lt;p&gt;If you're building with Supabase on .NET, this is also for you: tell me what's broken, what's missing, what's annoying. I have my own thoughts on that, but real pain points are better than assumptions.&lt;/p&gt;

&lt;p&gt;Stay tuned and Happy coding ✌️&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>dotnet</category>
      <category>opensource</category>
      <category>csharp</category>
    </item>
    <item>
      <title>How I Removed 1,500 Lines of Boilerplate with a Source Generator</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Tue, 08 Jul 2025 08:53:41 +0000</pubDate>
      <link>https://dev.to/tr00d/how-i-removed-1500-lines-of-boilerplate-with-a-source-generator-1ich</link>
      <guid>https://dev.to/tr00d/how-i-removed-1500-lines-of-boilerplate-with-a-source-generator-1ich</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/tr00d/why-i-use-and-abuse-the-builder-pattern-3lbm"&gt;previous blog post&lt;/a&gt;, I explained why I rely so heavily on the &lt;a href="https://refactoring.guru/design-patterns/builder" rel="noopener noreferrer"&gt;Builder&lt;/a&gt; pattern. It facilitates the creation of my requests, guiding developers when creating objects.&lt;/p&gt;

&lt;p&gt;This wasn't just a personal preference. I ended up there because Builders ticked all the boxes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predictable object creation&lt;/li&gt;
&lt;li&gt;Control over validation failure&lt;/li&gt;
&lt;li&gt;Support for both mandatory and optional parameters&lt;/li&gt;
&lt;li&gt;A way to guide users with a Fluent API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But implementing those builders came with a heavy cost: &lt;strong&gt;boilerplate code&lt;/strong&gt;. Each builder added 50+ lines of code on average; for simple/repetitive ones, and much more for complex ones. &lt;br&gt;
That doesn't scale well: multiply this by 30+ use cases, and you get a lot of code that you have to write and maintain.&lt;/p&gt;

&lt;p&gt;Let's address that particular problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  What do we need?
&lt;/h2&gt;

&lt;p&gt;The problem is not the builder itself. It's how much (repetitive) code it takes to get there, especially when a lot of them are very similar.&lt;/p&gt;

&lt;p&gt;What we want is a way to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declare which requests require a builder&lt;/li&gt;
&lt;li&gt;Declare mandatory and optional properties&lt;/li&gt;
&lt;li&gt;Add validation rules&lt;/li&gt;
&lt;li&gt;Return a Result upon creation, that will represent either a Request or a failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, we want the same benefits, but with zero boilerplate.&lt;/p&gt;

&lt;p&gt;Of course, we will not be able to apply this everywhere; some builders are quite specific, with internal behaviors. The goal is to remove the basic ones, the majority of them.&lt;/p&gt;
&lt;h2&gt;
  
  
  What are source generators?
&lt;/h2&gt;

&lt;p&gt;Source Generators let you write code that runs at compile-time and generates other code.&lt;/p&gt;

&lt;p&gt;In our case, we can write a class to make the generator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect specific attributes&lt;/li&gt;
&lt;li&gt;Create a builder dynamically&lt;/li&gt;
&lt;li&gt;Generate a &lt;code&gt;.g.cs&lt;/code&gt; file with all the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For us, it means fewer files to maintain, less code to write. We also keep a consistent pattern across the codebase. &lt;br&gt;
Also, adding a new builder is completely transparent; all we have to do is to create a new class with the rightattributes, and "voilà".&lt;/p&gt;
&lt;h2&gt;
  
  
  The Basics
&lt;/h2&gt;

&lt;p&gt;If you want to build something similar, here are the foundational steps you'll need to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new Class Library project for the Generator&lt;/li&gt;
&lt;li&gt;Create a Generator class that implements IIncrementalGenerator&lt;/li&gt;
&lt;li&gt;Use Roslyn's syntax/semantic model to detect classes and their attributes&lt;/li&gt;
&lt;li&gt;Generate new &lt;code&gt;.cs&lt;/code&gt; file using &lt;code&gt;SourceProductionContext&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's a minimal example of what the setup looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Generator&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BuilderGenerator&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IIncrementalGenerator&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IncrementalGeneratorInitializationContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;structDeclarations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;IdentifyBuilders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RegisterSourceOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;structDeclarations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;productionContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;structSymbols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;structSymbols&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GenerateSourceCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;productionContext&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GenerateSourceCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INamedTypeSymbol&lt;/span&gt; &lt;span class="n"&gt;structSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SourceProductionContext&lt;/span&gt; &lt;span class="n"&gt;productionContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;generatedCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// Generate the builder's code&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;structSymbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;Builder.g.cs"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;productionContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SourceText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;From&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generatedCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll walk you through the building blocks in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the Hood
&lt;/h2&gt;

&lt;p&gt;Here's how I structured the generator.&lt;/p&gt;

&lt;p&gt;I have four attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Builder" which will decorate a struct, marking them as requiring builder.&lt;/li&gt;
&lt;li&gt;"Mandatory" which will decorate a property, marking it as mandatory.&lt;/li&gt;
&lt;li&gt;"Optional" which will decorate a property, marking it as optional.&lt;/li&gt;
&lt;li&gt;"Validation" which will decorate a method, used to validate the request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generator will find all structs marked with &lt;code&gt;Builder&lt;/code&gt;...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;HasBuilderAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SyntaxNode&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;StructDeclarationSyntax&lt;/span&gt; &lt;span class="n"&gt;declaration&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;declaration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AttributeLists&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SelectMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntax&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;syntax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntax&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;syntax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;BuilderAttribute&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IncrementalValueProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ImmutableArray&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;INamedTypeSymbol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;IdentifyBuilders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;IncrementalGeneratorInitializationContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SyntaxProvider&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateSyntaxProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;HasBuilderAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetStructSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And fetch properties marked as &lt;code&gt;Mandatory&lt;/code&gt; or &lt;code&gt;Optional&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MandatoryProperty&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetMandatoryProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INamedTypeSymbol&lt;/span&gt; &lt;span class="n"&gt;structSymbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;GetMembersForAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;structSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MandatoryProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AttributeName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MandatoryProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromMember&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IPropertySymbol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetMembersForAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INamedTypeSymbol&lt;/span&gt; &lt;span class="n"&gt;structSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;attributeName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;structSymbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetMembers&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;OfType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IPropertySymbol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAttributes&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AttributeClass&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;attributeName&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When all the data is gathered, we proceed to create our Builder, line by line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our using statements&lt;/li&gt;
&lt;li&gt;The namespace&lt;/li&gt;
&lt;li&gt;Interface declarations&lt;/li&gt;
&lt;li&gt;Our builder&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We're essentially creating the entire file ourselves, as a &lt;code&gt;string&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GenerateCode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GenerateUsingStatements&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GenerateNamespace&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GenerateInterfaceDeclarations&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExtendTypeWithPartial&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GenerateBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;FormatCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GenerateUsingStatements&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"using Vonage.Common.Client;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"using Vonage.Common.Monads;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"using Vonage.Common.Validation;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAttributes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;First&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AttributeClass&lt;/span&gt;&lt;span class="p"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"BuilderAttribute"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConstructorArguments&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;First&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"using &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GenerateNamespace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContainingNamespace&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;ToDisplayString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$"namespace &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContainingNamespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToDisplayString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s"&gt;;\n\n"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GenerateInterfaceDeclarations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBuilderInterfaces&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builderInterface&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;builderInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BuildDeclaration&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example: from Request to Builder
&lt;/h2&gt;

&lt;p&gt;You'll find below an example: &lt;code&gt;VerifyCodeRequest&lt;/code&gt;, which allows us to verify a 2FA code with our [Verify (&lt;a href="https://developer.vonage.com/en/verify/overview" rel="noopener noreferrer"&gt;https://developer.vonage.com/en/verify/overview&lt;/a&gt;) API.&lt;/p&gt;

&lt;p&gt;This is the code from my initial request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Vonage.VerifyV2.VerifyCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// This request requires a builder&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;VerifyCodeRequest&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IVonageRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="c1"&gt;// Code is mandatory, and second property to set&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;JsonIgnore&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="c1"&gt;// RequestId is mandatory, and first property to set&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;RequestId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ValidationRule&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// ValidationRule for our builder&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;VerifyCodeNotEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;InputValidation&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;VerifyNotEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ValidationRule&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// ValidationRule for our builder&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;VerifyRequestIdNotEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;InputValidation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;VerifyNotEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is the builder (&lt;code&gt;VerifyCodeRequestBuilder.g.cs&lt;/code&gt;), generated by our source generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Vonage.Common.Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Vonage.Common.Monads&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Vonage.Common.Validation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Vonage.VerifyV2.VerifyCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBuilderForRequestId&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IBuilderForCode&lt;/span&gt; &lt;span class="nf"&gt;WithRequestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBuilderForCode&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IBuilderForOptional&lt;/span&gt; &lt;span class="nf"&gt;WithCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBuilderForOptional&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IVonageRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;VerifyCodeRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IBuilderForRequestId&lt;/span&gt; &lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;VerifyCodeRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;VerifyCodeRequestBuilder&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IBuilderForRequestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBuilderForCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBuilderForOptional&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;requestid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;VerifyCodeRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requestid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IBuilderForCode&lt;/span&gt; &lt;span class="nf"&gt;WithRequestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requestid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IBuilderForOptional&lt;/span&gt; &lt;span class="nf"&gt;WithCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;RequestId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requestid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputEvaluation&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;Evaluate&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;evaluation&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;evaluation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithRules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VerifyCodeNotEmpty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VerifyRequestIdNotEmpty&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably noticed a couple of other things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our builder is in the same namespace as our request (&lt;code&gt;Vonage.VerifyV2.VerifyCode&lt;/code&gt;), making it transparent for people who uses our code. They don't know, and they don't need to know, that the builder has been automatically generated.&lt;/li&gt;
&lt;li&gt;We also extend our partial Request to add a static method &lt;code&gt;Build()&lt;/code&gt; to initialize the builder with &lt;code&gt;Request.Build()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, here's a usage example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VerifyCodeRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithRequestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"68c2b32e-55ba-4a8e-b3fa-43b3ae6cd1fb"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"123456789"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, my builders were already thoroughly tested before I introduced source generators. I used my test suite to guarantee that no builder's public api changed in the process, making sure that not a single breaking change was introduced.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Talking about testing, it's relatively straightforward.&lt;/p&gt;

&lt;p&gt;You need to initialize your source generator (&lt;code&gt;BuilderGenerator&lt;/code&gt; is the generator we created earlier), run the generation and compare the result with your expectation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GenerateCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;inputCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;compilation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CSharpCompilation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestNamespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CSharpSyntaxTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ParseText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputCode&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MetadataReference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateFromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CSharpCompilationOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OutputKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DynamicallyLinkedLibrary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CSharpGeneratorDriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AttributesGenerator&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BuilderGenerator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunGeneratorsAndUpdateCompilation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;outputCompilation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;outputCompilation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SyntaxTrees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Last&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Theory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;VerifyCodeGeneration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;inputCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Files/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_Input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;expectedGeneratedCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Files/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_Expected.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;NormalizeLineBreaks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expectedGeneratedCode&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;NormalizeLineBreaks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;GenerateCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputCode&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each test data focuses on a specific feature.&lt;br&gt;
For example, here's my input file when testing a mandatory property with a validation rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Vonage.TestProduct.TestRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Vonage.Common.Validation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;MyRequest&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IVonageRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ValidationRule&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;VerifyName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;InputValidation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;VerifyNotEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's the expected output that I will compare to the generator's output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Vonage.Common.Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Vonage.Common.Monads&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Vonage.Common.Validation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Vonage.TestProduct.TestRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBuilderForName&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IBuilderForOptional&lt;/span&gt; &lt;span class="nf"&gt;WithName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBuilderForOptional&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IVonageRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;MyRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IBuilderForName&lt;/span&gt; &lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MyRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;MyRequestBuilder&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IBuilderForName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IBuilderForOptional&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IBuilderForOptional&lt;/span&gt; &lt;span class="nf"&gt;WithName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MyRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputEvaluation&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;Evaluate&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;evaluation&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;evaluation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithRules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VerifyName&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Everything I shared above is publicly available.&lt;/p&gt;

&lt;p&gt;Whether you'd like to verify I'm not lying, see the entire implementation or take some code, please yourself; it's all open-source code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SourceGenerator project: &lt;a href="https://github.com/Vonage/vonage-dotnet-sdk/tree/main/Vonage.SourceGenerator" rel="noopener noreferrer"&gt;https://github.com/Vonage/vonage-dotnet-sdk/tree/main/Vonage.SourceGenerator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SourceGenerator test project: &lt;a href="https://github.com/Vonage/vonage-dotnet-sdk/tree/main/Vonage.SourceGenerator.Test" rel="noopener noreferrer"&gt;https://github.com/Vonage/vonage-dotnet-sdk/tree/main/Vonage.SourceGenerator.Test&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VerifyCodeRequest&lt;/code&gt;: &lt;a href="https://github.com/Vonage/vonage-dotnet-sdk/blob/main/Vonage/VerifyV2/VerifyCode/VerifyCodeRequest.cs" rel="noopener noreferrer"&gt;https://github.com/Vonage/vonage-dotnet-sdk/blob/main/Vonage/VerifyV2/VerifyCode/VerifyCodeRequest.cs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VerifyCodeRequest&lt;/code&gt; tests: &lt;a href="https://github.com/Vonage/vonage-dotnet-sdk/blob/main/Vonage.Test/VerifyV2/VerifyCode/RequestBuilderTest.cs" rel="noopener noreferrer"&gt;https://github.com/Vonage/vonage-dotnet-sdk/blob/main/Vonage.Test/VerifyV2/VerifyCode/RequestBuilderTest.cs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;With source generators, I was (so far) able to remove roughly 1'500 lines of repetitive code without making compromises on functionalities, nor any change in my builder's public api. It is also much easier to add new builders now: a couple attributes on a request, and we're ready to roll.&lt;/p&gt;

&lt;p&gt;The next step is to iterate on my source generator to support more advanced use cases.I already handle more specific use cases that I didn't detailed above, like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/Vonage/vonage-dotnet-sdk/blob/main/Vonage.SourceGenerator.Test/Files/OptionalBoolean_Input.txt" rel="noopener noreferrer"&gt;Optional Booleans&lt;/a&gt; which defines a default value and exposes an explicit method to change the state, like &lt;code&gt;default is true, and "Disable" sets the value to false&lt;/code&gt;. This improves the experience overall by making the intent explicit, instead of relying on &lt;code&gt;true/false&lt;/code&gt; values.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Vonage/vonage-dotnet-sdk/blob/main/Vonage.SourceGenerator.Test/Files/OptionalWithDefault_Input.txt" rel="noopener noreferrer"&gt;Optional values with default&lt;/a&gt; which allows setting default values for Optional properties.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For sure, I won't be able to replace all my builders; but being able to substitute standard ones is already a big win.&lt;/p&gt;

&lt;p&gt;I hope you learned something today.&lt;br&gt;
Happy coding, and see you soon!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>monads</category>
      <category>design</category>
      <category>programming</category>
    </item>
    <item>
      <title>During presentations of "Throw exceptions... away from your codebase", I've been asked a lot "Why I use so much on the Builder pattern?". So, I just wrote a post about it. On the menu: Immutability, Parsing, Validation, and Fluent APIs.</title>
      <dc:creator>Guillaume Faas</dc:creator>
      <pubDate>Mon, 17 Feb 2025 06:11:05 +0000</pubDate>
      <link>https://dev.to/tr00d/during-presentations-of-throw-exceptions-away-from-your-codebase-ive-been-asked-a-lot-why-i-4l1f</link>
      <guid>https://dev.to/tr00d/during-presentations-of-throw-exceptions-away-from-your-codebase-ive-been-asked-a-lot-why-i-4l1f</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/tr00d/why-i-use-and-abuse-the-builder-pattern-3lbm" class="crayons-story__hidden-navigation-link"&gt;Why I use (and abuse) the Builder pattern&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/tr00d" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F981891%2F2064afc8-4d2a-46d9-9523-9f5756b14169.jpeg" alt="tr00d profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/tr00d" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Guillaume Faas
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Guillaume Faas
                
              
              &lt;div id="story-author-preview-content-2272740" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/tr00d" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F981891%2F2064afc8-4d2a-46d9-9523-9f5756b14169.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Guillaume Faas&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/tr00d/why-i-use-and-abuse-the-builder-pattern-3lbm" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 13 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/tr00d/why-i-use-and-abuse-the-builder-pattern-3lbm" id="article-link-2272740"&gt;
          Why I use (and abuse) the Builder pattern
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dotnet"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dotnet&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/monads"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;monads&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/design"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;design&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/tr00d/why-i-use-and-abuse-the-builder-pattern-3lbm" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;10&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/tr00d/why-i-use-and-abuse-the-builder-pattern-3lbm#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>dotnet</category>
      <category>monads</category>
      <category>design</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
