1 of 32

Stop Copy Pasting Code!

Use Source Generators Instead

drewfrisk.dev

2 of 32

Drew Frisk

Senior Software Engineer @ MetaFarms

https://drewfrisk.dev

https://github.com/MysterDru

/in/drewfrisk

drewfrisk.dev

3 of 32

A leading AgriTech company with a 20 year history in the swine production industry. We help pig producers identify problems in their inventory and manage the full life-cycle of a pig from birth to market.

drewfrisk.dev

4 of 32

Agenda

  • Why did we decide to create Source Generators?�
  • What is a Source Generator?�
  • Creating the Source Generator�
  • Life after Source Generators

drewfrisk.dev

5 of 32

Setting The Stage

Why did we decide to create source generators?

drewfrisk.dev

6 of 32

Our APIs

  • .NET 8 Web API�
  • APIs are CRUD�
    • Some custom commands for downstream logic�
  • 50-60% of our application is customer managed setup data - i.e dropdown values�
  • Extremely simple data schema

drewfrisk.dev

7 of 32

The Dilemma

  • Over the course of building our APIs, we recognized common patterns that resulted in a lot of copy paste activities for developers.
  • This led to inconsistencies:�
    • Some things didn’t get renamed correctly�
    • If we wanted to change patterns, it required touching 100’s of files�
  • The only difference between files was names of classes and routes.�
  • This meant more code to maintain, review, test, etc.

drewfrisk.dev

8 of 32

Sample API Schema

Northwind Sample Database

drewfrisk.dev

9 of 32

Project Structure

  • Each Slice Consists of
    • API Controller�
    • DTOs�
    • Validators (where appropriate)�
    • Data Access Service

    • Entity to DTO Projects�

* Entities reside in Data folder for simplicity with EF Core

drewfrisk.dev

10 of 32

Code Demo

What's the difference or similarities between the following code?

drewfrisk.dev

11 of 32

Consolidate and Abstract

Break apart the service interfaces

drewfrisk.dev

12 of 32

drewfrisk.dev

13 of 32

drewfrisk.dev

14 of 32

Roslyn Source Generators

What is a Source Generator?

drewfrisk.dev

15 of 32

Roslyn Source Generators

  • A Source Generator is a new kind of component that C# developers can write that lets you do two major things:

  • Retrieve a compilation object that represents all user code that is being compiled. This object can be inspected, and you can write code that works with the syntax and semantic models for the code being compiled, just like with analyzers today.

  • Generate C# source files that can be added to a compilation object during compilation. In other words, you can provide additional source code as input to a compilation while the code is being compiled.

drewfrisk.dev

16 of 32

Roslyn Source Generators

Source Generators

Compilation Runs

Source generator step of compilation

Generated source code added as input to compilation

Compilation resumes

Analyze source code

Generate new/additional source code

drewfrisk.dev

17 of 32

Analyze Source Code

  • Most source generators rely on a marker symbol.�
    • Usually a custom attribute defined and exported by the generator�
    • But can also be a base class, interface, etc.

  • When something is found in the compilation with the marker, that reference is added to the generation “pipeline”.

drewfrisk.dev

18 of 32

2 Core Apis

Syntax API

Concerned with the structure of the source code. It provides classes and methods to parse, create, and manipulate the syntax tree of a program.

Symbols API / Semantic Model

Deals with the semantic meaning of the code, such as the types, members, and other elements defined and referenced in the code. Provides similar functionality to working with Reflection.

drewfrisk.dev

19 of 32

Lets Remove the Repetitiveness

Creating a Source Generator

drewfrisk.dev

20 of 32

Create The Generator

  • Create a Class Library Project�
  • Must target NetStandard2.0�
  • It can be in the same solution as the consuming project�but are typically published as nuget packages.�
  • Contains at least 1 generator class

drewfrisk.dev

21 of 32

Create The Generator

Workflow of the Generator is 3 Primary Steps

drewfrisk.dev

22 of 32

Create The Generator

  1. Add markers to consuming project�
    1. Attribute�
    2. Interfaces�
  2. Find classes that have the attribute & transform to a semantic target�
  3. Generate code based on the semantic target

drewfrisk.dev

23 of 32

Step 1: Create Markers

  • Export a marker attribute to determine controller candidacy�
  • Export marker interfaces to determine controller action implementations��

drewfrisk.dev

24 of 32

Step 2: Find Classes

  • Now, on every keystroke the compilation will be searched for files that have our attribute.�
  • 2 sub-steps:
    • Find the syntax nodes that are annotated with our attribute�
    • When found, transform the syntax tree and semantic target that describes the controller to be generated.��

drewfrisk.dev

25 of 32

Step 3: Generate Source Code

  • Given the semantic targets, generate controllers
    • Class Shell
    • Attributes
    • Service Injection
    • Actions

drewfrisk.dev

26 of 32

Code Demo

Review the generator and see it in action

drewfrisk.dev

27 of 32

Things to Know

  • Incremental Generator pipelines must return value types for caching to work�
  • Performance of generators are incredibly important�
  • Nothing stops you from generating invalid code�
  • Source Generators work with .NET Framework 4.7.2

drewfrisk.dev

28 of 32

What Wasn’t Shown

  • Our Production Generators also handle:�
    • Authorization�
    • Authentication�
    • Documentation�
  • Unit Testing�
  • Packing and Distribution as Nuget

drewfrisk.dev

29 of 32

Now What?

Life After Source Generators

drewfrisk.dev

30 of 32

Life After Generators

  • We’ve removed a lot of code from our solution. �
    • For MetaFarms this has been over 100 controllers; which increases every sprint.
  • We don’t have to worry about how controllers are created and structured. They just work.�
  • We’ve saved several hours for the implementation time of an entity. �
  • We’ve added more generator usage beyond our controllers to improve team efficiency.

drewfrisk.dev

31 of 32

Other Source Generators

  • Localization from CSV files.�
  • Automatic generation of interfaces�
  • Dependency registration at runtime without using reflection.�
  • Data binding for MAUI

drewfrisk.dev

32 of 32

Questions & Resources

https://forms.gle/ScAYEtzXba8zNCCv8

Demo Files & Slides

https://drewfrisk.dev/sessions/kcdc-2024

Speaker Feedback

drewfrisk.dev