From 4e2fa1e253c427e2c0980d25ced9a2dcd4e28e32 Mon Sep 17 00:00:00 2001 From: Andrei Ignat Date: Sat, 4 Apr 2026 13:52:50 +0300 Subject: [PATCH 1/3] demo --- v2/RSCGExamplesData/GeneratorDataRec.json | 8 +++++- .../Aigamo.MatchGenerator/description.json | 22 ++++++++++++++++ .../Aigamo.MatchGenerator/src/EnumDemo.sln | 25 +++++++++++++++++++ .../src/EnumDemo/CarTypes.cs | 24 ++++++++++++++++++ .../src/EnumDemo/EnumDemo.csproj | 22 ++++++++++++++++ .../src/EnumDemo/Program.cs | 24 ++++++++++++++++++ 6 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/description.json create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo.sln create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/CarTypes.cs create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/EnumDemo.csproj create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/Program.cs diff --git a/v2/RSCGExamplesData/GeneratorDataRec.json b/v2/RSCGExamplesData/GeneratorDataRec.json index f350fe844..1dc5f9a9f 100644 --- a/v2/RSCGExamplesData/GeneratorDataRec.json +++ b/v2/RSCGExamplesData/GeneratorDataRec.json @@ -1606,5 +1606,11 @@ "Category": 6, "dtStart": "2026-04-07T00:00:00", "show": true - } + } , + { + "ID":"Aigamo.MatchGenerator", + "Category": 19, + "dtStart": "2026-04-05T00:00:00", + "show": true + } ] \ No newline at end of file diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/description.json b/v2/rscg_examples/Aigamo.MatchGenerator/description.json new file mode 100644 index 000000000..702c8dd59 --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/description.json @@ -0,0 +1,22 @@ +{ + "generator":{ + "name":"Aigamo.MatchGenerator", + "nuget":[ + "https://www.nuget.org/packages/Aigamo.MatchGenerator/" + ], + "link":"https://github.com/ycanardeau/MatchGenerator", + "author":"Aigamo", + "source":"https://github.com/ycanardeau/MatchGenerator" + }, + "data":{ + "goodFor":["Transform enums into tagged unions -with error in Match !"], + "csprojDemo":"EnumDemo.csproj", + "csFiles":["Program.cs","CarTypes.cs"], + "excludeDirectoryGenerated":[""], + "includeAdditionalFiles":[""] + }, + "links":{ + "blog":"", + "video":"" + } +} \ No newline at end of file diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo.sln b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo.sln new file mode 100644 index 000000000..ace1b5ec0 --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36401.2 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumDemo", "EnumDemo\EnumDemo.csproj", "{9D8848B1-F882-46F9-8036-C1C47BA503F0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9D8848B1-F882-46F9-8036-C1C47BA503F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D8848B1-F882-46F9-8036-C1C47BA503F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D8848B1-F882-46F9-8036-C1C47BA503F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D8848B1-F882-46F9-8036-C1C47BA503F0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {420BBB7E-4EC0-4A41-98F7-E573A6501983} + EndGlobalSection +EndGlobal diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/CarTypes.cs b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/CarTypes.cs new file mode 100644 index 000000000..3d7d1bc79 --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/CarTypes.cs @@ -0,0 +1,24 @@ +using Aigamo.MatchGenerator; +namespace EnumDemo; + +[GenerateMatch] +public enum CarTypes +{ + None, + Dacia, + + Tesla, + + BMW, + + Mercedes, +} + + +[GenerateMatch] +abstract record MaritalStatus; + +sealed record Single : MaritalStatus; +sealed record Married : MaritalStatus; +sealed record Divorced : MaritalStatus; +sealed record Widowed : MaritalStatus; \ No newline at end of file diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/EnumDemo.csproj b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/EnumDemo.csproj new file mode 100644 index 000000000..a4176c62c --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/EnumDemo.csproj @@ -0,0 +1,22 @@ + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + + diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/Program.cs b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/Program.cs new file mode 100644 index 000000000..9c5a006d1 --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/src/EnumDemo/Program.cs @@ -0,0 +1,24 @@ +// See https://aka.ms/new-console-template for more information +using EnumDemo; +using System.Reflection; + +Console.WriteLine("Hello, World!"); +CarTypes car = CarTypes.BMW; +var message = car.Match( + onBMW: () => "this is bmw", + onDacia: () => "this is dacia", + onMercedes: () => "this is mercedes", + onNone: () => "this is none", + onTesla: () => "this is tesla" + ); + +Console.WriteLine(message); +MaritalStatus maritalStatus = new Divorced(); + +var messageStatus = maritalStatus.Match( + onSingle: x => "single", + onMarried: x => "married", + onDivorced: x => "divorced", + onWidowed: x => "widowed" +); +Console.WriteLine(messageStatus); \ No newline at end of file From ec8b618680c4ed11467a2778df9f81b422e27350 Mon Sep 17 00:00:00 2001 From: Andrei Ignat Date: Sat, 4 Apr 2026 13:54:42 +0300 Subject: [PATCH 2/3] enum export --- README.md | 28 +- v2/Generator/all.csv | 1 + v2/RSCGExamplesData/GeneratorDataRec.json | 2 +- .../Aigamo.MatchGenerator/nuget.txt | 1 + .../Aigamo.MatchGenerator/readme.txt | 195 +++ .../src/.tours/Aigamo.MatchGenerator.tour | 60 + .../Aigamo.MatchGenerator/video.json | 39 + v2/rscg_examples_site/docs/Authors/Aigamo.md | 4 +- v2/rscg_examples_site/docs/Categories/Enum.md | 30 +- .../docs/Categories/_PrimitiveEnum.mdx | 28 +- .../RSCG-Examples/Aigamo.MatchGenerator.md | 1064 +++++++++++++++++ .../docs/RSCG-Examples/index.md | 13 +- v2/rscg_examples_site/docs/about.md | 2 +- v2/rscg_examples_site/docs/indexRSCG.md | 5 +- .../src/components/HomepageFeatures/index.js | 2 +- .../static/exports/RSCG.json | 8 + .../static/exports/RSCG.xlsx | Bin 13986 -> 14023 bytes 17 files changed, 1443 insertions(+), 39 deletions(-) create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/nuget.txt create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/readme.txt create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/src/.tours/Aigamo.MatchGenerator.tour create mode 100644 v2/rscg_examples/Aigamo.MatchGenerator/video.json create mode 100644 v2/rscg_examples_site/docs/RSCG-Examples/Aigamo.MatchGenerator.md diff --git a/README.md b/README.md index c1ce49854..ea967a67f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# RSCG - 265 Examples of Roslyn Source Code Generators / 16 created by Microsoft / +# RSCG - 266 Examples of Roslyn Source Code Generators / 16 created by Microsoft / -The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 265 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports. +The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 266 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports. This system serves as both a learning resource for .NET developers interested in source generators and an automated pipeline for maintaining up-to-date documentation about the RSCG ecosystem @@ -24,8 +24,30 @@ If you want to be notified each time I add a new RSCG example , please click htt ## Content -Those are the 265 Roslyn Source Code Generators that I have tested you can see and download source code example. +Those are the 266 Roslyn Source Code Generators that I have tested you can see and download source code example. ( including 16 from Microsoft ) +### 266. [Aigamo.MatchGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator) , in the [Enum](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enum) category + +Generated on : 2026-04-05 => 05 April 2026 + +
+ Expand + + + +Author: Aigamo + +Package Description + +Nuget: [https://www.nuget.org/packages/Aigamo.MatchGenerator/](https://www.nuget.org/packages/Aigamo.MatchGenerator/) + + +Link: [https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator) + +Source: [https://github.com/ycanardeau/MatchGenerator](https://github.com/ycanardeau/MatchGenerator) + +
+ ### 265. [lomapper](https://ignatandrei.github.io/RSCG_Examples/v2/docs/lomapper) , in the [Mapper](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#mapper) category Generated on : 2026-04-07 => 07 April 2026 diff --git a/v2/Generator/all.csv b/v2/Generator/all.csv index ac5b8cee7..d02dc1cee 100644 --- a/v2/Generator/all.csv +++ b/v2/Generator/all.csv @@ -264,3 +264,4 @@ Nr,Key,Source,Category 263,TaggedEnum, https://github.com/al0rid4l/SixTatami,Enum 264,Najlot.Audit.SourceGenerator, https://github.com/najlot/Audit,Audit 265,lomapper, https://github.com/jdtoon/lomapper,Mapper +266,Aigamo.MatchGenerator, https://github.com/ycanardeau/MatchGenerator,Enum diff --git a/v2/RSCGExamplesData/GeneratorDataRec.json b/v2/RSCGExamplesData/GeneratorDataRec.json index 1dc5f9a9f..828643b2e 100644 --- a/v2/RSCGExamplesData/GeneratorDataRec.json +++ b/v2/RSCGExamplesData/GeneratorDataRec.json @@ -1612,5 +1612,5 @@ "Category": 19, "dtStart": "2026-04-05T00:00:00", "show": true - } + } ] \ No newline at end of file diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/nuget.txt b/v2/rscg_examples/Aigamo.MatchGenerator/nuget.txt new file mode 100644 index 000000000..882e74f60 --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/nuget.txt @@ -0,0 +1 @@ +Package Description \ No newline at end of file diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/readme.txt b/v2/rscg_examples/Aigamo.MatchGenerator/readme.txt new file mode 100644 index 000000000..9538875be --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/readme.txt @@ -0,0 +1,195 @@ +# MatchGenerator + +**Bring exhaustive pattern matching to C# enums and unions with zero boilerplate.** + +[MatchGenerator](https://github.com/ycanardeau/MatchGenerator) is a Roslyn source generator that creates `Match` extension methods for your enums and discriminated-union-like types, enabling concise, expressive, and compile-time safe branching. + +## Features + +- Generate `Match` extension methods for enums and unions +- Exhaustive by design (no missing cases) +- Attribute-driven (opt-in per type) +- Supports generics (`Match`) +- Respects effective accessibility +- Zero runtime cost (pure source generation) + +## Getting Started + +### 1. Install the package + +```bash +dotnet add package Aigamo.MatchGenerator +``` + +### 2. Annotate your type + +#### Enum example + +```csharp +using Aigamo.MatchGenerator; + +[GenerateMatch] +public enum Gender +{ + Male = 1, + Female, +} +``` + +#### Union example + +```csharp +using Aigamo.MatchGenerator; + +[GenerateMatch] +abstract record MaritalStatus; + +sealed record Single : MaritalStatus; +sealed record Married : MaritalStatus; +sealed record Divorced : MaritalStatus; +sealed record Widowed : MaritalStatus; +``` + +### 3. Use `Match` + +#### Enum + +```csharp +var message = gender.Match( + onMale: () => "male", + onFemale: () => "female" +); +``` + +#### Union + +```csharp +var message = maritalStatus.Match( + onSingle: x => "single", + onMarried: x => "married", + onDivorced: x => "divorced", + onWidowed: x => "widowed" +); +``` + +## Why use MatchGenerator? + +### Without MatchGenerator + +#### Enum + +```csharp +var message = gender switch +{ + Gender.Male => "male", + Gender.Female => "female", + _ => throw new UnreachableException(), +}; +``` + +#### Union + +```csharp +var message = maritalStatus switch +{ + Single x => "single", + Married x => "married", + Divorced x => "divorced", + Widowed x => "widowed", + _ => throw new UnreachableException(), +}; +``` + +### With MatchGenerator + +```csharp +var message = gender.Match( + onMale: () => "male", + onFemale: () => "female" +); +``` + +- More concise +- More readable +- No default case required +- Compile-time safety + +## Exhaustiveness Guarantee + +All cases must be handled. + +If a new enum value or union type is added: + +```csharp +public enum Gender +{ + Male = 1, + Female, + Other, +} +``` + +or + +```csharp +sealed record Separated : MaritalStatus; +``` + +Existing `Match` calls will fail to compile until updated. This ensures no cases are missed. + +## Generated Code (Example) + +### Enum + +```csharp +internal static class GenderMatchExtensions +{ + public static U Match( + this Gender value, + Func onFemale, + Func onMale + ) + { + return value switch + { + Gender.Female => onFemale(), + Gender.Male => onMale(), + _ => throw new UnreachableException(), + }; + } +} +``` + +### Union + +```csharp +internal static class MaritalStatusMatchExtensions +{ + public static U Match( + this MaritalStatus value, + Func onDivorced, + Func onMarried, + Func onSingle, + Func onWidowed + ) + { + return value switch + { + Divorced x => onDivorced(x), + Married x => onMarried(x), + Single x => onSingle(x), + Widowed x => onWidowed(x), + _ => throw new UnreachableException(), + }; + } +} +``` + +## References + +- [Introducing C# Source Generators - .NET Blog](https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/) +- [roslyn/docs/features/source-generators.cookbook.md at main · dotnet/roslyn](https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md) +- [roslyn/docs/features/incremental-generators.cookbook.md at main · dotnet/roslyn](https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.cookbook.md) +- [Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F# by Scott Wlaschin](https://pragprog.com/titles/swdddf/domain-modeling-made-functional/) +- [It Seems the C# Team Is Finally Considering Supporting Discriminated Unions - DEV Community](https://dev.to/canro91/it-seems-the-c-team-is-finally-considering-supporting-discriminated-unions-59k3) +- [salvois/DiscriminatedOnions: A stinky but tasty hack to emulate F#-like discriminated unions in C#](https://github.com/salvois/DiscriminatedOnions) diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/src/.tours/Aigamo.MatchGenerator.tour b/v2/rscg_examples/Aigamo.MatchGenerator/src/.tours/Aigamo.MatchGenerator.tour new file mode 100644 index 000000000..d112de3e9 --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/src/.tours/Aigamo.MatchGenerator.tour @@ -0,0 +1,60 @@ + +{ + "$schema": "https://aka.ms/codetour-schema", + "title": "Aigamo.MatchGenerator", + "steps": + [ + { + "file": "EnumDemo/EnumDemo.csproj", + "description": "First, we add Nuget [Aigamo.MatchGenerator](https://www.nuget.org/packages/Aigamo.MatchGenerator/) in csproj ", + "pattern": "Aigamo.MatchGenerator" + } + + ,{ + "file": "EnumDemo/CarTypes.cs", + "description": "File CarTypes.cs ", + "pattern": "this is the code" + } + + ,{ + "file": "EnumDemo/Program.cs", + "description": "File Program.cs \r\n>> dotnet run --project EnumDemo/EnumDemo.csproj ", + "pattern": "this is the code" + } + + + ,{ + "file": "EnumDemo/obj/GX/TaggedEnum/TaggedEnum.TaggedEnumSourceGenerator/TaggedEnumAttribute.g.cs", + "description": "Generated File 5 from 5 : TaggedEnumAttribute.g.cs ", + "line": 1 + } + + ,{ + "file": "EnumDemo/obj/GX/TaggedEnum/TaggedEnum.TaggedEnumSourceGenerator/EnumDemoEnumDemo.CarTypesTaggedEnum.g.cs", + "description": "Generated File 4 from 5 : EnumDemoEnumDemo.CarTypesTaggedEnum.g.cs ", + "line": 1 + } + + ,{ + "file": "EnumDemo/obj/GX/Aigamo.MatchGenerator/Aigamo.MatchGenerator.SourceGenerator/MaritalStatusMatchExtensions.g.cs", + "description": "Generated File 3 from 5 : MaritalStatusMatchExtensions.g.cs ", + "line": 1 + } + + ,{ + "file": "EnumDemo/obj/GX/Aigamo.MatchGenerator/Aigamo.MatchGenerator.SourceGenerator/GenerateMatchAttribute.g.cs", + "description": "Generated File 2 from 5 : GenerateMatchAttribute.g.cs ", + "line": 1 + } + + ,{ + "file": "EnumDemo/obj/GX/Aigamo.MatchGenerator/Aigamo.MatchGenerator.SourceGenerator/CarTypesMatchExtensions.g.cs", + "description": "Generated File 1 from 5 : CarTypesMatchExtensions.g.cs ", + "line": 1 + } + + ], + + "ref": "main" + +} \ No newline at end of file diff --git a/v2/rscg_examples/Aigamo.MatchGenerator/video.json b/v2/rscg_examples/Aigamo.MatchGenerator/video.json new file mode 100644 index 000000000..232aeeeed --- /dev/null +++ b/v2/rscg_examples/Aigamo.MatchGenerator/video.json @@ -0,0 +1,39 @@ +{ + "scriptName": "Aigamo.MatchGenerator", + "steps": +[ + {"typeStep":"exec","arg":"clipchamp.exe launch"}, + {"typeStep":"text","arg": "Welcome to Roslyn Examples"}, + {"typeStep":"text","arg":"If you want to see more examples , see List Of RSCG"}, + {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG"}, + {"typeStep":"text","arg": "My name is Andrei Ignat and I am deeply fond of Roslyn Source Code Generator. "}, + +{"typeStep":"text","arg": "Today I will present Aigamo.MatchGenerator . Transform enums into tagged unions -with error in Match ! ."}, +{"typeStep":"browser","arg":"https://www.nuget.org/packages/Aigamo.MatchGenerator/"}, +{"typeStep":"text","arg": "The whole example is here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator"}, +{"typeStep":"text","arg": "You can download the code from here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator#download-example-net--c-"}, +{"typeStep":"text","arg":"Here is the code downloaded "}, +{"typeStep":"exec","arg":"explorer.exe /select,D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\Aigamo.MatchGenerator\\src\\EnumDemo.sln"}, +{"typeStep":"text","arg": "So , let's start the project with Visual Studio Code "}, +{"typeStep":"stepvscode","arg": "-n D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\Aigamo.MatchGenerator\\src"}, + +{"typeStep":"text","arg": "To use it ,you will put the Nuget Aigamo.MatchGenerator into the csproj "}, + +{"typeStep":"stepvscode","arg": "-r -g D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\Aigamo.MatchGenerator\\src\\EnumDemo\\EnumDemo.csproj"}, + +{"typeStep":"text","arg": "And now I will show you an example of using Aigamo.MatchGenerator"}, + +{"typeStep":"hide","arg": "now execute the tour in VSCode"}, +{"typeStep":"tour", "arg": "src/.tours/"}, +{"typeStep":"text","arg":" And I will execute the project"}, +{"typeStep":"showproj", "arg":"EnumDemo.csproj"}, +{"typeStep":"text","arg":" This concludes the project"}, +{"typeStep":"waitseconds","arg":"30"}, +{"typeStep":"text","arg": "Remember, you can download the code from here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator#download-example-net--c-", +SpeakTest=" "}, +{"typeStep":"waitseconds","arg":"30"}, +] +} diff --git a/v2/rscg_examples_site/docs/Authors/Aigamo.md b/v2/rscg_examples_site/docs/Authors/Aigamo.md index 8a9f2edb4..58b2591b8 100644 --- a/v2/rscg_examples_site/docs/Authors/Aigamo.md +++ b/v2/rscg_examples_site/docs/Authors/Aigamo.md @@ -1,7 +1,9 @@ # Author : Aigamo -Number RSCG: 1 +Number RSCG: 2 1 [ResXGenerator](/docs/ResXGenerator) [![Nuget](https://img.shields.io/nuget/dt/Aigamo.ResXGenerator?label=Aigamo.ResXGenerator)](https://www.nuget.org/packages/Aigamo.ResXGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ycanardeau/ResXGenerator?style=social) 2023-10-02 + 2 [Aigamo.MatchGenerator](/docs/Aigamo.MatchGenerator) [![Nuget](https://img.shields.io/nuget/dt/Aigamo.MatchGenerator?label=Aigamo.MatchGenerator)](https://www.nuget.org/packages/Aigamo.MatchGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ycanardeau/MatchGenerator?style=social) 2026-04-05 + diff --git a/v2/rscg_examples_site/docs/Categories/Enum.md b/v2/rscg_examples_site/docs/Categories/Enum.md index fbec34fe5..a1861e2a2 100644 --- a/v2/rscg_examples_site/docs/Categories/Enum.md +++ b/v2/rscg_examples_site/docs/Categories/Enum.md @@ -1,30 +1,32 @@

Enum

-Number RSCG: 13 +Number RSCG: 14 - 1 [CredFetoEnum](/docs/CredFetoEnum) [![Nuget](https://img.shields.io/nuget/dt/Credfeto.Enumeration.Source.Generation?label=Credfeto.Enumeration.Source.Generation)](https://www.nuget.org/packages/Credfeto.Enumeration.Source.Generation/) ![GitHub Repo stars](https://img.shields.io/github/stars/credfeto/credfeto-enum-source-generation?style=social) 2023-10-12 + 1 [Aigamo.MatchGenerator](/docs/Aigamo.MatchGenerator) [![Nuget](https://img.shields.io/nuget/dt/Aigamo.MatchGenerator?label=Aigamo.MatchGenerator)](https://www.nuget.org/packages/Aigamo.MatchGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ycanardeau/MatchGenerator?style=social) 2026-04-05 - 2 [EnumClass](/docs/EnumClass) [![Nuget](https://img.shields.io/nuget/dt/EnumClass.Generator?label=EnumClass.Generator)](https://www.nuget.org/packages/EnumClass.Generator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ashenBlade/EnumClass?style=social) 2023-08-08 + 2 [CredFetoEnum](/docs/CredFetoEnum) [![Nuget](https://img.shields.io/nuget/dt/Credfeto.Enumeration.Source.Generation?label=Credfeto.Enumeration.Source.Generation)](https://www.nuget.org/packages/Credfeto.Enumeration.Source.Generation/) ![GitHub Repo stars](https://img.shields.io/github/stars/credfeto/credfeto-enum-source-generation?style=social) 2023-10-12 - 3 [EnumsEnhanced](/docs/EnumsEnhanced) [![Nuget](https://img.shields.io/nuget/dt/EnumsEnhanced?label=EnumsEnhanced)](https://www.nuget.org/packages/EnumsEnhanced/) ![GitHub Repo stars](https://img.shields.io/github/stars/snowberry-software/EnumsEnhanced?style=social) 2025-08-05 + 3 [EnumClass](/docs/EnumClass) [![Nuget](https://img.shields.io/nuget/dt/EnumClass.Generator?label=EnumClass.Generator)](https://www.nuget.org/packages/EnumClass.Generator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ashenBlade/EnumClass?style=social) 2023-08-08 - 4 [EnumUtilities](/docs/EnumUtilities) [![Nuget](https://img.shields.io/nuget/dt/Raiqub.Generators.EnumUtilities?label=Raiqub.Generators.EnumUtilities)](https://www.nuget.org/packages/Raiqub.Generators.EnumUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/skarllot/EnumUtilities?style=social) 2024-04-05 + 4 [EnumsEnhanced](/docs/EnumsEnhanced) [![Nuget](https://img.shields.io/nuget/dt/EnumsEnhanced?label=EnumsEnhanced)](https://www.nuget.org/packages/EnumsEnhanced/) ![GitHub Repo stars](https://img.shields.io/github/stars/snowberry-software/EnumsEnhanced?style=social) 2025-08-05 - 5 [Flaggen](/docs/Flaggen) [![Nuget](https://img.shields.io/nuget/dt/Flaggen?label=Flaggen)](https://www.nuget.org/packages/Flaggen/) ![GitHub Repo stars](https://img.shields.io/github/stars/ricardoboss/Flaggen?style=social) 2025-07-23 + 5 [EnumUtilities](/docs/EnumUtilities) [![Nuget](https://img.shields.io/nuget/dt/Raiqub.Generators.EnumUtilities?label=Raiqub.Generators.EnumUtilities)](https://www.nuget.org/packages/Raiqub.Generators.EnumUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/skarllot/EnumUtilities?style=social) 2024-04-05 - 6 [FusionReactor](/docs/FusionReactor) [![Nuget](https://img.shields.io/nuget/dt/FusionReactor.SourceGenerators.EnumExtensions?label=FusionReactor.SourceGenerators.EnumExtensions)](https://www.nuget.org/packages/FusionReactor.SourceGenerators.EnumExtensions) ![GitHub Repo stars](https://img.shields.io/github/stars/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions?style=social) 2024-04-06 + 6 [Flaggen](/docs/Flaggen) [![Nuget](https://img.shields.io/nuget/dt/Flaggen?label=Flaggen)](https://www.nuget.org/packages/Flaggen/) ![GitHub Repo stars](https://img.shields.io/github/stars/ricardoboss/Flaggen?style=social) 2025-07-23 - 7 [Genbox.FastEnum](/docs/Genbox.FastEnum) [![Nuget](https://img.shields.io/nuget/dt/Genbox.FastEnum?label=Genbox.FastEnum)](https://www.nuget.org/packages/Genbox.FastEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/Genbox/FastEnum?style=social) 2025-08-03 + 7 [FusionReactor](/docs/FusionReactor) [![Nuget](https://img.shields.io/nuget/dt/FusionReactor.SourceGenerators.EnumExtensions?label=FusionReactor.SourceGenerators.EnumExtensions)](https://www.nuget.org/packages/FusionReactor.SourceGenerators.EnumExtensions) ![GitHub Repo stars](https://img.shields.io/github/stars/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions?style=social) 2024-04-06 - 8 [jos.enumeration](/docs/jos.enumeration) [![Nuget](https://img.shields.io/nuget/dt/jos.enumeration?label=jos.enumeration)](https://www.nuget.org/packages/jos.enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/joseftw/jos.enumeration?style=social) 2025-07-20 + 8 [Genbox.FastEnum](/docs/Genbox.FastEnum) [![Nuget](https://img.shields.io/nuget/dt/Genbox.FastEnum?label=Genbox.FastEnum)](https://www.nuget.org/packages/Genbox.FastEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/Genbox/FastEnum?style=social) 2025-08-03 - 9 [NetEscapades.EnumGenerators](/docs/NetEscapades.EnumGenerators) [![Nuget](https://img.shields.io/nuget/dt/NetEscapades.EnumGenerators?label=NetEscapades.EnumGenerators)](https://www.nuget.org/packages/NetEscapades.EnumGenerators/) ![GitHub Repo stars](https://img.shields.io/github/stars/andrewlock/NetEscapades.EnumGenerators?style=social) 2023-04-16 + 9 [jos.enumeration](/docs/jos.enumeration) [![Nuget](https://img.shields.io/nuget/dt/jos.enumeration?label=jos.enumeration)](https://www.nuget.org/packages/jos.enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/joseftw/jos.enumeration?style=social) 2025-07-20 - 10 [PMart.Enumeration](/docs/PMart.Enumeration) [![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration.Generator?label=PMart.Enumeration.Generator)](https://www.nuget.org/packages/PMart.Enumeration.Generator/)[![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration?label=PMart.Enumeration)](https://www.nuget.org/packages/PMart.Enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/p-martinho/Enumeration?style=social) 2025-03-25 + 10 [NetEscapades.EnumGenerators](/docs/NetEscapades.EnumGenerators) [![Nuget](https://img.shields.io/nuget/dt/NetEscapades.EnumGenerators?label=NetEscapades.EnumGenerators)](https://www.nuget.org/packages/NetEscapades.EnumGenerators/) ![GitHub Repo stars](https://img.shields.io/github/stars/andrewlock/NetEscapades.EnumGenerators?style=social) 2023-04-16 - 11 [RapidEnum](/docs/RapidEnum) [![Nuget](https://img.shields.io/nuget/dt/RapidEnum?label=RapidEnum)](https://www.nuget.org/packages/RapidEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/hanachiru/RapidEnum?style=social) 2025-10-04 + 11 [PMart.Enumeration](/docs/PMart.Enumeration) [![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration.Generator?label=PMart.Enumeration.Generator)](https://www.nuget.org/packages/PMart.Enumeration.Generator/)[![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration?label=PMart.Enumeration)](https://www.nuget.org/packages/PMart.Enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/p-martinho/Enumeration?style=social) 2025-03-25 - 12 [requiredenum](/docs/requiredenum) [![Nuget](https://img.shields.io/nuget/dt/requiredenum?label=requiredenum)](https://www.nuget.org/packages/requiredenum/) ![GitHub Repo stars](https://img.shields.io/github/stars/emptycoder/RequiredEnum?style=social) 2025-08-14 + 12 [RapidEnum](/docs/RapidEnum) [![Nuget](https://img.shields.io/nuget/dt/RapidEnum?label=RapidEnum)](https://www.nuget.org/packages/RapidEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/hanachiru/RapidEnum?style=social) 2025-10-04 - 13 [TaggedEnum](/docs/TaggedEnum) [![Nuget](https://img.shields.io/nuget/dt/TaggedEnum?label=TaggedEnum)](https://www.nuget.org/packages/TaggedEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/al0rid4l/SixTatami?style=social) 2026-04-05 + 13 [requiredenum](/docs/requiredenum) [![Nuget](https://img.shields.io/nuget/dt/requiredenum?label=requiredenum)](https://www.nuget.org/packages/requiredenum/) ![GitHub Repo stars](https://img.shields.io/github/stars/emptycoder/RequiredEnum?style=social) 2025-08-14 + + 14 [TaggedEnum](/docs/TaggedEnum) [![Nuget](https://img.shields.io/nuget/dt/TaggedEnum?label=TaggedEnum)](https://www.nuget.org/packages/TaggedEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/al0rid4l/SixTatami?style=social) 2026-04-05 \ No newline at end of file diff --git a/v2/rscg_examples_site/docs/Categories/_PrimitiveEnum.mdx b/v2/rscg_examples_site/docs/Categories/_PrimitiveEnum.mdx index 6cb075e15..a2c5e0cac 100644 --- a/v2/rscg_examples_site/docs/Categories/_PrimitiveEnum.mdx +++ b/v2/rscg_examples_site/docs/Categories/_PrimitiveEnum.mdx @@ -1,30 +1,32 @@ ### Category "Enum" has the following generators: - 1 [CredFetoEnum](/docs/CredFetoEnum) [![Nuget](https://img.shields.io/nuget/dt/Credfeto.Enumeration.Source.Generation?label=Credfeto.Enumeration.Source.Generation)](https://www.nuget.org/packages/Credfeto.Enumeration.Source.Generation/) ![GitHub Repo stars](https://img.shields.io/github/stars/credfeto/credfeto-enum-source-generation?style=social) 2023-10-12 + 1 [Aigamo.MatchGenerator](/docs/Aigamo.MatchGenerator) [![Nuget](https://img.shields.io/nuget/dt/Aigamo.MatchGenerator?label=Aigamo.MatchGenerator)](https://www.nuget.org/packages/Aigamo.MatchGenerator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ycanardeau/MatchGenerator?style=social) 2026-04-05 - 2 [EnumClass](/docs/EnumClass) [![Nuget](https://img.shields.io/nuget/dt/EnumClass.Generator?label=EnumClass.Generator)](https://www.nuget.org/packages/EnumClass.Generator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ashenBlade/EnumClass?style=social) 2023-08-08 + 2 [CredFetoEnum](/docs/CredFetoEnum) [![Nuget](https://img.shields.io/nuget/dt/Credfeto.Enumeration.Source.Generation?label=Credfeto.Enumeration.Source.Generation)](https://www.nuget.org/packages/Credfeto.Enumeration.Source.Generation/) ![GitHub Repo stars](https://img.shields.io/github/stars/credfeto/credfeto-enum-source-generation?style=social) 2023-10-12 - 3 [EnumsEnhanced](/docs/EnumsEnhanced) [![Nuget](https://img.shields.io/nuget/dt/EnumsEnhanced?label=EnumsEnhanced)](https://www.nuget.org/packages/EnumsEnhanced/) ![GitHub Repo stars](https://img.shields.io/github/stars/snowberry-software/EnumsEnhanced?style=social) 2025-08-05 + 3 [EnumClass](/docs/EnumClass) [![Nuget](https://img.shields.io/nuget/dt/EnumClass.Generator?label=EnumClass.Generator)](https://www.nuget.org/packages/EnumClass.Generator/) ![GitHub Repo stars](https://img.shields.io/github/stars/ashenBlade/EnumClass?style=social) 2023-08-08 - 4 [EnumUtilities](/docs/EnumUtilities) [![Nuget](https://img.shields.io/nuget/dt/Raiqub.Generators.EnumUtilities?label=Raiqub.Generators.EnumUtilities)](https://www.nuget.org/packages/Raiqub.Generators.EnumUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/skarllot/EnumUtilities?style=social) 2024-04-05 + 4 [EnumsEnhanced](/docs/EnumsEnhanced) [![Nuget](https://img.shields.io/nuget/dt/EnumsEnhanced?label=EnumsEnhanced)](https://www.nuget.org/packages/EnumsEnhanced/) ![GitHub Repo stars](https://img.shields.io/github/stars/snowberry-software/EnumsEnhanced?style=social) 2025-08-05 - 5 [Flaggen](/docs/Flaggen) [![Nuget](https://img.shields.io/nuget/dt/Flaggen?label=Flaggen)](https://www.nuget.org/packages/Flaggen/) ![GitHub Repo stars](https://img.shields.io/github/stars/ricardoboss/Flaggen?style=social) 2025-07-23 + 5 [EnumUtilities](/docs/EnumUtilities) [![Nuget](https://img.shields.io/nuget/dt/Raiqub.Generators.EnumUtilities?label=Raiqub.Generators.EnumUtilities)](https://www.nuget.org/packages/Raiqub.Generators.EnumUtilities/) ![GitHub Repo stars](https://img.shields.io/github/stars/skarllot/EnumUtilities?style=social) 2024-04-05 - 6 [FusionReactor](/docs/FusionReactor) [![Nuget](https://img.shields.io/nuget/dt/FusionReactor.SourceGenerators.EnumExtensions?label=FusionReactor.SourceGenerators.EnumExtensions)](https://www.nuget.org/packages/FusionReactor.SourceGenerators.EnumExtensions) ![GitHub Repo stars](https://img.shields.io/github/stars/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions?style=social) 2024-04-06 + 6 [Flaggen](/docs/Flaggen) [![Nuget](https://img.shields.io/nuget/dt/Flaggen?label=Flaggen)](https://www.nuget.org/packages/Flaggen/) ![GitHub Repo stars](https://img.shields.io/github/stars/ricardoboss/Flaggen?style=social) 2025-07-23 - 7 [Genbox.FastEnum](/docs/Genbox.FastEnum) [![Nuget](https://img.shields.io/nuget/dt/Genbox.FastEnum?label=Genbox.FastEnum)](https://www.nuget.org/packages/Genbox.FastEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/Genbox/FastEnum?style=social) 2025-08-03 + 7 [FusionReactor](/docs/FusionReactor) [![Nuget](https://img.shields.io/nuget/dt/FusionReactor.SourceGenerators.EnumExtensions?label=FusionReactor.SourceGenerators.EnumExtensions)](https://www.nuget.org/packages/FusionReactor.SourceGenerators.EnumExtensions) ![GitHub Repo stars](https://img.shields.io/github/stars/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions?style=social) 2024-04-06 - 8 [jos.enumeration](/docs/jos.enumeration) [![Nuget](https://img.shields.io/nuget/dt/jos.enumeration?label=jos.enumeration)](https://www.nuget.org/packages/jos.enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/joseftw/jos.enumeration?style=social) 2025-07-20 + 8 [Genbox.FastEnum](/docs/Genbox.FastEnum) [![Nuget](https://img.shields.io/nuget/dt/Genbox.FastEnum?label=Genbox.FastEnum)](https://www.nuget.org/packages/Genbox.FastEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/Genbox/FastEnum?style=social) 2025-08-03 - 9 [NetEscapades.EnumGenerators](/docs/NetEscapades.EnumGenerators) [![Nuget](https://img.shields.io/nuget/dt/NetEscapades.EnumGenerators?label=NetEscapades.EnumGenerators)](https://www.nuget.org/packages/NetEscapades.EnumGenerators/) ![GitHub Repo stars](https://img.shields.io/github/stars/andrewlock/NetEscapades.EnumGenerators?style=social) 2023-04-16 + 9 [jos.enumeration](/docs/jos.enumeration) [![Nuget](https://img.shields.io/nuget/dt/jos.enumeration?label=jos.enumeration)](https://www.nuget.org/packages/jos.enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/joseftw/jos.enumeration?style=social) 2025-07-20 - 10 [PMart.Enumeration](/docs/PMart.Enumeration) [![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration.Generator?label=PMart.Enumeration.Generator)](https://www.nuget.org/packages/PMart.Enumeration.Generator/)[![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration?label=PMart.Enumeration)](https://www.nuget.org/packages/PMart.Enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/p-martinho/Enumeration?style=social) 2025-03-25 + 10 [NetEscapades.EnumGenerators](/docs/NetEscapades.EnumGenerators) [![Nuget](https://img.shields.io/nuget/dt/NetEscapades.EnumGenerators?label=NetEscapades.EnumGenerators)](https://www.nuget.org/packages/NetEscapades.EnumGenerators/) ![GitHub Repo stars](https://img.shields.io/github/stars/andrewlock/NetEscapades.EnumGenerators?style=social) 2023-04-16 - 11 [RapidEnum](/docs/RapidEnum) [![Nuget](https://img.shields.io/nuget/dt/RapidEnum?label=RapidEnum)](https://www.nuget.org/packages/RapidEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/hanachiru/RapidEnum?style=social) 2025-10-04 + 11 [PMart.Enumeration](/docs/PMart.Enumeration) [![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration.Generator?label=PMart.Enumeration.Generator)](https://www.nuget.org/packages/PMart.Enumeration.Generator/)[![Nuget](https://img.shields.io/nuget/dt/PMart.Enumeration?label=PMart.Enumeration)](https://www.nuget.org/packages/PMart.Enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/p-martinho/Enumeration?style=social) 2025-03-25 - 12 [requiredenum](/docs/requiredenum) [![Nuget](https://img.shields.io/nuget/dt/requiredenum?label=requiredenum)](https://www.nuget.org/packages/requiredenum/) ![GitHub Repo stars](https://img.shields.io/github/stars/emptycoder/RequiredEnum?style=social) 2025-08-14 + 12 [RapidEnum](/docs/RapidEnum) [![Nuget](https://img.shields.io/nuget/dt/RapidEnum?label=RapidEnum)](https://www.nuget.org/packages/RapidEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/hanachiru/RapidEnum?style=social) 2025-10-04 - 13 [TaggedEnum](/docs/TaggedEnum) [![Nuget](https://img.shields.io/nuget/dt/TaggedEnum?label=TaggedEnum)](https://www.nuget.org/packages/TaggedEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/al0rid4l/SixTatami?style=social) 2026-04-05 + 13 [requiredenum](/docs/requiredenum) [![Nuget](https://img.shields.io/nuget/dt/requiredenum?label=requiredenum)](https://www.nuget.org/packages/requiredenum/) ![GitHub Repo stars](https://img.shields.io/github/stars/emptycoder/RequiredEnum?style=social) 2025-08-14 + + 14 [TaggedEnum](/docs/TaggedEnum) [![Nuget](https://img.shields.io/nuget/dt/TaggedEnum?label=TaggedEnum)](https://www.nuget.org/packages/TaggedEnum/) ![GitHub Repo stars](https://img.shields.io/github/stars/al0rid4l/SixTatami?style=social) 2026-04-05 ### See category diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/Aigamo.MatchGenerator.md b/v2/rscg_examples_site/docs/RSCG-Examples/Aigamo.MatchGenerator.md new file mode 100644 index 000000000..fc013f400 --- /dev/null +++ b/v2/rscg_examples_site/docs/RSCG-Examples/Aigamo.MatchGenerator.md @@ -0,0 +1,1064 @@ +--- +sidebar_position: 2660 +title: 266 - Aigamo.MatchGenerator +description: Transform enums into tagged unions -with error in Match ! +slug: /Aigamo.MatchGenerator +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import TOCInline from '@theme/TOCInline'; +import SameCategory from '../Categories/_PrimitiveEnum.mdx'; + +# Aigamo.MatchGenerator by Aigamo + + + + +## NuGet / site data +[![Nuget](https://img.shields.io/nuget/dt/Aigamo.MatchGenerator?label=Aigamo.MatchGenerator)](https://www.nuget.org/packages/Aigamo.MatchGenerator/) +[![GitHub last commit](https://img.shields.io/github/last-commit/ycanardeau/MatchGenerator?label=updated)](https://github.com/ycanardeau/MatchGenerator) +![GitHub Repo stars](https://img.shields.io/github/stars/ycanardeau/MatchGenerator?style=social) + +## Details + +### Info +:::info + +Name: **Aigamo.MatchGenerator** + +Package Description + +Author: Aigamo + +NuGet: +*https://www.nuget.org/packages/Aigamo.MatchGenerator/* + + +You can find more details at https://github.com/ycanardeau/MatchGenerator + +Source: https://github.com/ycanardeau/MatchGenerator + +::: + +### Author +:::note +Aigamo +![Alt text](https://github.com/ycanardeau.png) +::: + +## Original Readme +:::note + +### MatchGenerator + +**Bring exhaustive pattern matching to C# enums and unions with zero boilerplate.** + +[MatchGenerator](https://github.com/ycanardeau/MatchGenerator) is a Roslyn source generator that creates `Match` extension methods for your enums and discriminated-union-like types, enabling concise, expressive, and compile-time safe branching. + +###### Features + +- Generate `Match` extension methods for enums and unions +- Exhaustive by design (no missing cases) +- Attribute-driven (opt-in per type) +- Supports generics (`Match`) +- Respects effective accessibility +- Zero runtime cost (pure source generation) + +###### Getting Started + +######### 1. Install the package + +```bash +dotnet add package Aigamo.MatchGenerator +``` + +######### 2. Annotate your type + +########## Enum example + +```csharp +using Aigamo.MatchGenerator; + +[GenerateMatch] +public enum Gender +{ + Male = 1, + Female, +} +``` + +########## Union example + +```csharp +using Aigamo.MatchGenerator; + +[GenerateMatch] +abstract record MaritalStatus; + +sealed record Single : MaritalStatus; +sealed record Married : MaritalStatus; +sealed record Divorced : MaritalStatus; +sealed record Widowed : MaritalStatus; +``` + +######### 3. Use `Match` + +########## Enum + +```csharp +var message = gender.Match( + onMale: () => "male", + onFemale: () => "female" +); +``` + +########## Union + +```csharp +var message = maritalStatus.Match( + onSingle: x => "single", + onMarried: x => "married", + onDivorced: x => "divorced", + onWidowed: x => "widowed" +); +``` + +###### Why use MatchGenerator? + +######### Without MatchGenerator + +########## Enum + +```csharp +var message = gender switch +{ + Gender.Male => "male", + Gender.Female => "female", + _ => throw new UnreachableException(), +}; +``` + +########## Union + +```csharp +var message = maritalStatus switch +{ + Single x => "single", + Married x => "married", + Divorced x => "divorced", + Widowed x => "widowed", + _ => throw new UnreachableException(), +}; +``` + +######### With MatchGenerator + +```csharp +var message = gender.Match( + onMale: () => "male", + onFemale: () => "female" +); +``` + +- More concise +- More readable +- No default case required +- Compile-time safety + +###### Exhaustiveness Guarantee + +All cases must be handled. + +If a new enum value or union type is added: + +```csharp +public enum Gender +{ + Male = 1, + Female, + Other, +} +``` + +or + +```csharp +sealed record Separated : MaritalStatus; +``` + +Existing `Match` calls will fail to compile until updated. This ensures no cases are missed. + +###### Generated Code (Example) + +######### Enum + +```csharp +internal static class GenderMatchExtensions +{ + public static U Match( + this Gender value, + Func onFemale, + Func onMale + ) + { + return value switch + { + Gender.Female => onFemale(), + Gender.Male => onMale(), + _ => throw new UnreachableException(), + }; + } +} +``` + +######### Union + +```csharp +internal static class MaritalStatusMatchExtensions +{ + public static U Match( + this MaritalStatus value, + Func onDivorced, + Func onMarried, + Func onSingle, + Func onWidowed + ) + { + return value switch + { + Divorced x => onDivorced(x), + Married x => onMarried(x), + Single x => onSingle(x), + Widowed x => onWidowed(x), + _ => throw new UnreachableException(), + }; + } +} +``` + +###### References + +- [Introducing C# Source Generators - .NET Blog](https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/) +- [roslyn/docs/features/source-generators.cookbook.md at main · dotnet/roslyn](https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md) +- [roslyn/docs/features/incremental-generators.cookbook.md at main · dotnet/roslyn](https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.cookbook.md) +- [Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F### by Scott Wlaschin](https://pragprog.com/titles/swdddf/domain-modeling-made-functional/) +- [It Seems the C# Team Is Finally Considering Supporting Discriminated Unions - DEV Community](https://dev.to/canro91/it-seems-the-c-team-is-finally-considering-supporting-discriminated-unions-59k3) +- [salvois/DiscriminatedOnions: A stinky but tasty hack to emulate F#-like discriminated unions in C#](https://github.com/salvois/DiscriminatedOnions) + + +::: + +### About +:::note + +Transform enums into tagged unions -with error in Match ! + + +::: + +## How to use + +### Example (source csproj, source files) + + + + + +This is the CSharp Project that references **Aigamo.MatchGenerator** +```xml showLineNumbers {16} + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + + + +``` + + + + + + This is the use of **Aigamo.MatchGenerator** in *Program.cs* + +```csharp showLineNumbers +// See https://aka.ms/new-console-template for more information +using EnumDemo; +using System.Reflection; + +Console.WriteLine("Hello, World!"); +CarTypes car = CarTypes.BMW; +var message = car.Match( + onBMW: () => "this is bmw", + onDacia: () => "this is dacia", + onMercedes: () => "this is mercedes", + onNone: () => "this is none", + onTesla: () => "this is tesla" + ); + +Console.WriteLine(message); +MaritalStatus maritalStatus = new Divorced(); + +var messageStatus = maritalStatus.Match( + onSingle: x => "single", + onMarried: x => "married", + onDivorced: x => "divorced", + onWidowed: x => "widowed" +); +Console.WriteLine(messageStatus); +``` + + + + + This is the use of **Aigamo.MatchGenerator** in *CarTypes.cs* + +```csharp showLineNumbers +using Aigamo.MatchGenerator; +namespace EnumDemo; + +[GenerateMatch] +public enum CarTypes +{ + None, + Dacia, + + Tesla, + + BMW, + + Mercedes, +} + + +[GenerateMatch] +abstract record MaritalStatus; + +sealed record Single : MaritalStatus; +sealed record Married : MaritalStatus; +sealed record Divorced : MaritalStatus; +sealed record Widowed : MaritalStatus; +``` + + + + +### Generated Files + +Those are taken from $(BaseIntermediateOutputPath)\GX + + + + +```csharp showLineNumbers +// +using System; +using System.Diagnostics; + +namespace EnumDemo; + +public static class CarTypesMatchExtensions +{ + public static U Match( + this CarTypes value, + Func onBMW, + Func onDacia, + Func onMercedes, + Func onNone, + Func onTesla + ) + { + return value switch + { + CarTypes.BMW => onBMW(), + CarTypes.Dacia => onDacia(), + CarTypes.Mercedes => onMercedes(), + CarTypes.None => onNone(), + CarTypes.Tesla => onTesla(), + _ => throw new UnreachableException(), + }; + } +} + +``` + + + + +```csharp showLineNumbers +using System; + +namespace Aigamo.MatchGenerator; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum)] +internal sealed class GenerateMatchAttribute : Attribute; +``` + + + + +```csharp showLineNumbers +// +using System; +using System.Diagnostics; + +namespace EnumDemo; + +internal static class MaritalStatusMatchExtensions +{ + public static U Match( + this MaritalStatus value, + Func onDivorced, + Func onMarried, + Func onSingle, + Func onWidowed + ) + { + return value switch + { + Divorced x => onDivorced(x), + Married x => onMarried(x), + Single x => onSingle(x), + Widowed x => onWidowed(x), + _ => throw new UnreachableException(), + }; + } +} + +``` + + + + +```csharp showLineNumbers +// +#nullable enable +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics; +using System.Text.Json; +using System.Text.Json.Serialization; +using TaggedEnum; + +namespace EnumDemo; + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public static class EnumDemoCarTypesExtension { + private static readonly Dictionary ValueNameMap = new(new EnumDemoCarTypesComparer()) { + + {global::EnumDemo.CarTypes.None, "None"}, + {global::EnumDemo.CarTypes.Dacia, "Dacia"}, + {global::EnumDemo.CarTypes.Tesla, "Tesla"}, + {global::EnumDemo.CarTypes.BMW, "BMW"}, + {global::EnumDemo.CarTypes.Mercedes, "Mercedes"}, + }; + + + + + + + + + + extension(global::EnumDemo.CarTypes self) { + public string Data { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + get => + self switch { + + global::EnumDemo.CarTypes.None => (string)"this is none", + global::EnumDemo.CarTypes.Dacia => (string)"this is dacia", + global::EnumDemo.CarTypes.Tesla => (string)"this is tesla", + global::EnumDemo.CarTypes.BMW => (string)"this is bwm", + global::EnumDemo.CarTypes.Mercedes => (string)"this is mercedes", + _ => DataNotFoundException.ThrowWithMessage($"Data of {ValueNameMap[self]} not found.") + }; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + public static string ToStringFast(this global::EnumDemo.CarTypes self) + => self switch { + + global::EnumDemo.CarTypes.None => "None", + global::EnumDemo.CarTypes.Dacia => "Dacia", + global::EnumDemo.CarTypes.Tesla => "Tesla", + global::EnumDemo.CarTypes.BMW => "BMW", + global::EnumDemo.CarTypes.Mercedes => "Mercedes", + _ => UnreachableException.ThrowWithMessage("Never reach here.") + }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + public static bool HasName(this global::EnumDemo.CarTypes self, string name) + => self.ToStringFast() == name; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + public static bool HasData(this global::EnumDemo.CarTypes self, string data) + => self.Data == data; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + public static bool Equals(this global::EnumDemo.CarTypes self, global::EnumDemo.CarTypes v) + => self == v; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + public static bool TryGetDataByName(string name, [NotNullWhen(true)]out string? v) { + v = name switch { + + "None" => (string)"this is none", + "Dacia" => (string)"this is dacia", + "Tesla" => (string)"this is tesla", + "BMW" => (string)"this is bwm", + "Mercedes" => (string)"this is mercedes", + _ => null + }; + return v is not null; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + public static bool TryGetValueByName(string name, [NotNullWhen(true)]out global::EnumDemo.CarTypes? v) { + v = name switch { + + "None" => global::EnumDemo.CarTypes.None, + "Dacia" => global::EnumDemo.CarTypes.Dacia, + "Tesla" => global::EnumDemo.CarTypes.Tesla, + "BMW" => global::EnumDemo.CarTypes.BMW, + "Mercedes" => global::EnumDemo.CarTypes.Mercedes, + _ => null + }; + return v is not null; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] + public static bool TryGetValueByData(string data, [NotNullWhen(true)]out global::EnumDemo.CarTypes? v) { + v = data switch { + + (string)"this is none" => global::EnumDemo.CarTypes.None, + (string)"this is dacia" => global::EnumDemo.CarTypes.Dacia, + (string)"this is tesla" => global::EnumDemo.CarTypes.Tesla, + (string)"this is bwm" => global::EnumDemo.CarTypes.BMW, + (string)"this is mercedes" => global::EnumDemo.CarTypes.Mercedes, + _ => null + }; + return v is not null; + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +internal sealed class EnumDemoCarTypesComparer: IEqualityComparer { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(global::EnumDemo.CarTypes x, global::EnumDemo.CarTypes y) => x == y; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetHashCode([DisallowNull] global::EnumDemo.CarTypes obj) => (int)obj; +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +internal sealed class EnumDemoCarTypesstringComparer: IEqualityComparer { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(string? x, string? y) => x == y; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetHashCode([DisallowNull] string obj) => obj.GetHashCode(); +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class EnumDemoCarTypesToDataConverter: JsonConverter { + public override global::EnumDemo.CarTypes Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + string? token = reader.GetString(); + return string.IsNullOrEmpty(token) + ? JsonException.ThrowWithMessage($"Couldn't convert data \"{token}\" to global::EnumDemo.CarTypes.") + : EnumDemoCarTypesExtension.TryGetValueByData(token, out var result) + ? result.Value : JsonException.ThrowWithMessage($"Couldn't find \"{token}\" in global::EnumDemo.CarTypes data."); + } + + public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes value, JsonSerializerOptions options) { + writer.WriteStringValue(value.Data); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class EnumDemoCarTypesArrayToDataArrayConverter: JsonConverter { + public override global::EnumDemo.CarTypes[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByData( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes[] arr, JsonSerializerOptions options) { + writer.WriteStartArray(); + for (int i = 0, len = arr.Length; i < len; ++i) { + writer.WriteStringValue(arr[i].Data); + } + writer.WriteEndArray(); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class NullableEnumDemoCarTypesArrayToDataArrayConverter: JsonConverter { + public override global::EnumDemo.CarTypes?[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.Null: + list.Add(null); + continue; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByData( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes?[] arr, JsonSerializerOptions options) { + writer.WriteStartArray(); + for (int i = 0, len = arr.Length; i < len; ++i) { + var v = arr[i]; + if (v is null) { + writer.WriteNullValue(); + } else { + writer.WriteStringValue(v.Value.Data); + } + + } + writer.WriteEndArray(); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class EnumDemoCarTypesEnumerableToDataEnumerableConverter: JsonConverter> { + public override IEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByData( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, IEnumerable values, JsonSerializerOptions options) { + writer.WriteStartArray(); + foreach (var v in values) { + writer.WriteStringValue(v.Data); + } + writer.WriteEndArray(); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class NullableEnumDemoCarTypesEnumerableToDataEnumerableConverter: JsonConverter> { + public override IEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.Null: + list.Add(null); + continue; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByData( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes data.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, IEnumerable values, JsonSerializerOptions options) { + writer.WriteStartArray(); + foreach (var v in values) { + if (v is null) { + writer.WriteNullValue(); + } else { + writer.WriteStringValue(v.Value.Data); + } + } + writer.WriteEndArray(); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class EnumDemoCarTypesToNameConverter: JsonConverter { + public override global::EnumDemo.CarTypes Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + string? token = reader.GetString(); + return string.IsNullOrEmpty(token) + ? JsonException.ThrowWithMessage($"Couldn't convert name \"{token}\" to global::EnumDemo.CarTypes.") + : EnumDemoCarTypesExtension.TryGetValueByName(token, out var result) + ? result.Value : JsonException.ThrowWithMessage($"Couldn't find \"{token}\" in global::EnumDemo.CarTypes name."); + } + + public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes value, JsonSerializerOptions options) { + writer.WriteStringValue(value.ToStringFast()); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class EnumDemoCarTypesArrayToNameArrayConverter: JsonConverter { + public override global::EnumDemo.CarTypes[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByName( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes[] arr, JsonSerializerOptions options) { + writer.WriteStartArray(); + for (int i = 0, len = arr.Length; i < len; ++i) { + writer.WriteStringValue(arr[i].ToStringFast()); + } + writer.WriteEndArray(); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class NullableEnumDemoCarTypesArrayToNameArrayConverter: JsonConverter { + public override global::EnumDemo.CarTypes?[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.Null: + list.Add(null); + continue; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByName( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, global::EnumDemo.CarTypes?[] arr, JsonSerializerOptions options) { + writer.WriteStartArray(); + for (int i = 0, len = arr.Length; i < len; ++i) { + var v = arr[i]; + if (v is null) { + writer.WriteNullValue(); + } else { + writer.WriteStringValue(v.Value.ToStringFast()); + } + } + writer.WriteEndArray(); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class EnumDemoCarTypesEnumerableToNameEnumerableConverter: JsonConverter> { + public override IEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByName( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, IEnumerable values, JsonSerializerOptions options) { + writer.WriteStartArray(); + foreach (var v in values) { + writer.WriteStringValue(v.ToStringFast()); + } + writer.WriteEndArray(); + } +} + +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("TaggedEnum", "1.0")] +public sealed class NullableEnumDemoCarTypesEnumerableToNameEnumerableConverter: JsonConverter> { + public override IEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + var list = new List(); + while (reader.Read()) { + switch (reader.TokenType) { + case JsonTokenType.StartArray: + continue; + case JsonTokenType.EndArray: + goto label; + case JsonTokenType.Null: + list.Add(null); + continue; + case JsonTokenType.String: + var v = reader.GetString() is not {} token ? UnreachableException.ThrowWithMessage("JsonTokenType is string but reader.GetString() is null.") : token; + list.Add(EnumDemoCarTypesExtension.TryGetValueByName( + v, + out var item) + ? item!.Value : JsonException.ThrowWithMessage($"Couldn't find \"{v}\" in global::EnumDemo.CarTypes name.")); + continue; + default: + continue; + } + } + label: + return list.ToArray(); + } + + public override void Write(Utf8JsonWriter writer, IEnumerable values, JsonSerializerOptions options) { + writer.WriteStartArray(); + foreach (var v in values) { + if (v is null) { + writer.WriteNullValue(); + } else { + writer.WriteStringValue(v.Value.ToStringFast()); + } + } + writer.WriteEndArray(); + } +} + +``` + + + + +```csharp showLineNumbers +// +#nullable enable + +using System.Text.Json; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace TaggedEnum; + +internal static class JsonExceptionExtensions { + extension(JsonException) { + [DoesNotReturn] + public static T ThrowWithMessage(string msg) + => throw new JsonException(msg); + } +} + +internal static class UnreachableExceptionExtensions { + extension(UnreachableException) { + [DoesNotReturn] + public static T ThrowWithMessage(string msg) + => throw new UnreachableException(msg); + } +} + +#pragma warning disable CA1050 // Declare types in namespaces +[AttributeUsage( + AttributeTargets.Field, + Inherited = false, + AllowMultiple = false + )] +internal sealed class Data(TValue v): Attribute { + public TValue V \{ get; private set; \} = v; +} + +[AttributeUsage( + AttributeTargets.Field, + Inherited = false, + AllowMultiple = false + )] +// TValue default is string +internal sealed class Data: Attribute { + public object? V \{ get; } + + public Data(object str) { + V = str; + } + + public Data() {} +} +#pragma warning restore CA1050 // Declare types in namespaces + +#pragma warning disable CA1050 // Declare types in namespaces +[AttributeUsage( + AttributeTargets.Enum, + Inherited = false, + AllowMultiple = false + )] +internal sealed class Tagged: Attribute { + public bool Inline = true; + + public bool UseSwitch = true; + + public bool AllowDuplicate = false; +} + +[AttributeUsage( + AttributeTargets.Enum, + Inherited = false, + AllowMultiple = false + )] +// TValue default is string +internal sealed class Tagged: Attribute { + public bool UseAll = false; + + public bool Inline = true; + + public bool UseSwitch = true; + + public bool AllowDuplicate = false; +} +#pragma warning restore CA1050 // Declare types in namespaces + +public sealed class DataNotFoundException(string msg): Exception(msg) { + [DoesNotReturn] + public static T ThrowWithMessage(string message) => throw new DataNotFoundException(message); +} +``` + + + + +## Useful + +### Download Example (.NET C#) + +:::tip + +[Download Example project Aigamo.MatchGenerator ](/sources/Aigamo.MatchGenerator.zip) + +::: + + +### Share Aigamo.MatchGenerator + + + +https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator + + + diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/index.md b/v2/rscg_examples_site/docs/RSCG-Examples/index.md index 07ebaad94..49568d458 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/index.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/index.md @@ -1,7 +1,7 @@ --- sidebar_position: 30 -title: 265 RSCG list by category -description: 265 RSCG list by category +title: 266 RSCG list by category +description: 266 RSCG list by category slug: /rscg-examples --- @@ -812,7 +812,7 @@ import DocCardList from '@theme/DocCardList'; ## Enum
- Expand Enum =>examples:13 + Expand Enum =>examples:14 @@ -878,6 +878,11 @@ import DocCardList from '@theme/DocCardList'; [TaggedEnum](/docs/TaggedEnum) + + + +[Aigamo.MatchGenerator](/docs/Aigamo.MatchGenerator) +
@@ -1953,6 +1958,8 @@ flowchart LR; Enum--> TaggedEnum((TaggedEnum)) + Enum--> Aigamo.MatchGenerator((Aigamo.MatchGenerator)) + Equals--> GeneratorEquals((GeneratorEquals)) Equals--> Equatable.Generator((Equatable.Generator)) diff --git a/v2/rscg_examples_site/docs/about.md b/v2/rscg_examples_site/docs/about.md index e4f2b5edf..dd1a1c667 100644 --- a/v2/rscg_examples_site/docs/about.md +++ b/v2/rscg_examples_site/docs/about.md @@ -6,7 +6,7 @@ title: About ## Content You will find here code examples -of 265 Roslyn Source Code Generator (RSCG) +of 266 Roslyn Source Code Generator (RSCG) that can be useful for you. That means, you will write more elegant and concise code - even if the generators code is not always nice to look. ## Are those examples ready for production? diff --git a/v2/rscg_examples_site/docs/indexRSCG.md b/v2/rscg_examples_site/docs/indexRSCG.md index b48ea8bb3..d11728ca5 100644 --- a/v2/rscg_examples_site/docs/indexRSCG.md +++ b/v2/rscg_examples_site/docs/indexRSCG.md @@ -7,9 +7,9 @@ slug: /List-of-RSCG import useBaseUrl from '@docusaurus/useBaseUrl'; -## 265 RSCG with examples in descending chronological order +## 266 RSCG with examples in descending chronological order -This is the list of 265 ( 16 from Microsoft) RSCG with examples +This is the list of 266 ( 16 from Microsoft) RSCG with examples [See by category](/docs/rscg-examples) [See as json](/exports/RSCG.json) [See as Excel](/exports/RSCG.xlsx) @@ -20,6 +20,7 @@ This is the list of 265 ( 16 from Microsoft) RSCG with examples | No | Name | Date | Category | | --------- | ----- | ---- | -------- | +|266| [Aigamo.MatchGenerator by Aigamo ](/docs/Aigamo.MatchGenerator)|2026-04-05 => 05 April 2026 | [Enum](/docs/Categories/Enum) | |265| [lomapper by Junaid Desai ](/docs/lomapper)|2026-04-07 => 07 April 2026 | [Mapper](/docs/Categories/Mapper) | |264| [Najlot.Audit.SourceGenerator by Najlot ](/docs/Najlot.Audit.SourceGenerator)|2026-04-06 => 06 April 2026 | [Audit](/docs/Categories/Audit) | |263| [TaggedEnum by Alor'idal ](/docs/TaggedEnum)|2026-04-05 => 05 April 2026 | [Enum](/docs/Categories/Enum) | diff --git a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js index 575a489d1..6e89d6f35 100644 --- a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js +++ b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js @@ -4,7 +4,7 @@ import styles from './styles.module.css'; const FeatureList = [ { -title: '265 Examples (16 from MSFT)', +title: '266 Examples (16 from MSFT)', Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, description: ( <> diff --git a/v2/rscg_examples_site/static/exports/RSCG.json b/v2/rscg_examples_site/static/exports/RSCG.json index ae106ef76..381671514 100644 --- a/v2/rscg_examples_site/static/exports/RSCG.json +++ b/v2/rscg_examples_site/static/exports/RSCG.json @@ -2121,6 +2121,14 @@ "Source": "https://github.com/jdtoon/lomapper", "Category": "Mapper", "AddedOn": "2026-04-07T00:00:00" + }, + { + "Name": "Aigamo.MatchGenerator", + "Link": "https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator", + "NuGet": "https://www.nuget.org/packages/Aigamo.MatchGenerator/", + "Source": "https://github.com/ycanardeau/MatchGenerator", + "Category": "Enum", + "AddedOn": "2026-04-05T00:00:00" } ] } \ No newline at end of file diff --git a/v2/rscg_examples_site/static/exports/RSCG.xlsx b/v2/rscg_examples_site/static/exports/RSCG.xlsx index 054011545cb258f7a395edd69dc3b8e143848a0a..2550b66b3262a4e651653c0177024d830a520efe 100644 GIT binary patch delta 871 zcmZ3Kdpx&3z?+#xgn@yBgW+giON?O4&f2{U3=B$)3=I50x*|uvJijPADL+43uOc_6 zx8IZRkO7bDdZ9{w&0xpSXfXxFZ3RsicI3JUhZi=;%{R!uXM_vF0#qRk!O`!+9ZFspB|n>=Z?*xE;iUtc_0rz663 zzOX#+PUXty|KHDkb?eFk@2f`_aqA2A&*j=^ynR`^z@{@#{k0w~&#z=h_3EkkhEMYt zH!<#K$~$Ukec z4#)rbv;V(6%zg%NP#=HsXy4`uhSH1zsm3N|Mv3OhMwUs&CMk)glXn}*ae&

4;9n z;nUY1oHyc*_HAO>({n#EG~&R#-j=x=zIt`Et%)pD{2?UqZ}x?o$DLnwe!BBg zUGLQVrTZ>MuPFPNRI%8{_tC$Fe=i-rDQqSW3ldQ3+x*s8n~@Wq3MVU?nnZ(mkceVn zuw-Fi;02~h1b78x0#j&lNo7uIF(`cocr!AIFd&jMB2t+cBoO+5tj$c5FEU9@K4r=S z4rx$iOulC-X0_Omfg!#qHK$l#4@9CH2#S$gK<#^h`9liDz%P^a%ru#f=1qWH@%0|1T8z)Wj?T`CB$&IHn zU9)QLCkg*a$2)dCmNWe6IL&MA((8H${@$PS$-Z-etyzJ^yL}F4PL@wEbvSY=)ndW6 zu-bLIE@gb(sOMEtairYlL{xf#|FcJiOYA3hH2du|{+^d2uxag6Z>`6h^M7-rdiGR& z!>5gZ4l?qAe7>YZw`Z~*1B2q*&8L}K_3XYD`8~|GdS(+mvEu7Go%1Rd<^eI^q7Stn zxOwe;de@Qtrrq;H@1E+O|Nr}cc9^jY;4pmn<0$jyt%lN!0)_^rsj10^Nya9r1}4d- z=93>7$#H-zYwO+kXEK|yM!jL)VFMo5^-2ZnHMKi~MFKaKyp(#v)Z%l~Eyr`h6f?`{ zHkp;-E22bPc}iYf>U^O7^8>@a`25*-E2WNVA2+F3zHpriN7=FM&96=7Y^tqjxm&jR z`NX1|9)ATUX{hUEz9{DN?>PCzCU8|vLb%$spy%p!*A zf9s32vOM Date: Sat, 4 Apr 2026 13:56:35 +0300 Subject: [PATCH 3/3] zip --- v2/book/examples/Aigamo.MatchGenerator.html | 79 ++++++++++++++++++ v2/book/list.html | 6 +- v2/book/pandocHTML.yaml | 1 + v2/docFind.json | 6 ++ .../static/exports/RSCG.xlsx | Bin 14023 -> 14024 bytes .../static/sources/Aigamo.MatchGenerator.zip | Bin 0 -> 1740 bytes 6 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 v2/book/examples/Aigamo.MatchGenerator.html create mode 100644 v2/rscg_examples_site/static/sources/Aigamo.MatchGenerator.zip diff --git a/v2/book/examples/Aigamo.MatchGenerator.html b/v2/book/examples/Aigamo.MatchGenerator.html new file mode 100644 index 000000000..c4dc964f0 --- /dev/null +++ b/v2/book/examples/Aigamo.MatchGenerator.html @@ -0,0 +1,79 @@ + +

RSCG nr 266 : Aigamo.MatchGenerator

+ +

Info

+Nuget : https://www.nuget.org/packages/Aigamo.MatchGenerator/ + +

You can find more details at : https://github.com/ycanardeau/MatchGenerator

+ +

Author :Aigamo

+ +

Source: https://github.com/ycanardeau/MatchGenerator

+ +

About

+ +Transform enums into tagged unions -with error in Match ! + +

+ How to use +

+

+ Add reference to the Aigamo.MatchGenerator in the csproj +

+ + +

This was for me the starting code

+ +
+ I have coded the file Program.cs +
+ +
+ +
+ I have coded the file CarTypes.cs +
+ +
+

And here are the generated files

+ +
+ The file generated is CarTypesMatchExtensions.g.cs +
+ + +
+ The file generated is GenerateMatchAttribute.g.cs +
+ + +
+ The file generated is MaritalStatusMatchExtensions.g.cs +
+ + +
+ The file generated is EnumDemoEnumDemo.CarTypesTaggedEnum.g.cs +
+ + +
+ The file generated is TaggedEnumAttribute.g.cs +
+ + +

+ You can download the code and this page as pdf from + + https://ignatandrei.github.io/RSCG_Examples/v2/docs/Aigamo.MatchGenerator + +

+ + +

+ You can see the whole list at + + https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG + +

+ diff --git a/v2/book/list.html b/v2/book/list.html index 3ae5686f7..c97eb1c61 100644 --- a/v2/book/list.html +++ b/v2/book/list.html @@ -17,7 +17,7 @@

-This is the list of 265 RSCG with examples => +This is the list of 266 RSCG with examples =>

@@ -1086,6 +1086,10 @@

+ + + +
265 lomapper
266Aigamo.MatchGenerator
diff --git a/v2/book/pandocHTML.yaml b/v2/book/pandocHTML.yaml index 2288a1a35..13327cbc4 100644 --- a/v2/book/pandocHTML.yaml +++ b/v2/book/pandocHTML.yaml @@ -279,6 +279,7 @@ input-files: - examples/TaggedEnum.html - examples/Najlot.Audit.SourceGenerator.html - examples/lomapper.html +- examples/Aigamo.MatchGenerator.html # or you may use input-file: with a single value # defaults: diff --git a/v2/docFind.json b/v2/docFind.json index 5ce850fef..daca589f4 100644 --- a/v2/docFind.json +++ b/v2/docFind.json @@ -1588,5 +1588,11 @@ "category": "Mapper", "href": "/RSCG_Examples/v2/docs/lomapper/", "body": "LoMapper - Lightweight Object Mapper using compile-time source generation. Zero runtime reflection." + }, + { + "title": "Aigamo.MatchGenerator", + "category": "Enum", + "href": "/RSCG_Examples/v2/docs/Aigamo.MatchGenerator/", + "body": "Package Description" } ] \ No newline at end of file diff --git a/v2/rscg_examples_site/static/exports/RSCG.xlsx b/v2/rscg_examples_site/static/exports/RSCG.xlsx index 2550b66b3262a4e651653c0177024d830a520efe..3e5e4ac417901fc597cadaee477951adae8be0fa 100644 GIT binary patch delta 656 zcmX?}dm^_!z?+#xgn@yBgMmN4CB~{to@Fls1A`JH0|P&huE^0Z&o9bO%FoZ%tH{mi z?LW=eWFX*LzjWqaF&-gj2Ju-E+kdex<+yu@Vh}udQ zi7xrf!eZsSws1L@-on{y6JnsP(NF(nMH5waZaHO9@uzy(AJvCbj&kuGKg)N-_~!ON_7;7g7UyZ^Gvl85 z?(*22)2X}1_K&^Xl~T9I)4m*C#H}yb-^{hq_4(S z8~^QRWa7`?yr1cv9tS7{{ym;^a`RS0X+{CV6oXU)Q}aYqV~bRi#6;uC4~*nEK}sfd zgs|S8%x)>ZocRJ z=BI6XDQ0T!P+)(yVLqt)52pqL`&nVc2pet#*7+PH}&Q}`~^%75ljpW!azFOIX|x? zHE*-Fi4Y?=)IjNGva6{nFeoS2m|B9U?WQj90G-TiW{4DYwr2Jq6?JAZjO>$Vo2juG JnF0-E007@W38nx5 delta 656 zcmX?+dpx&3z?+#xgn@yBgW+giON?O4&f2{U3=B$)3=I50x*|uvJijPADL+43uOc_6 zx8IZRkO7bDdZ9{w&0xpSXfXxFZ3RsicI3JUhZi=;%{R!uXM_vF0#qRk!O`!+9ZFspB|n>=Z?*xE;iUtc_0rz663 zzOX#+PUXty|KHDkb?eFk@2f`_aqA2A&*j=^ynR`^z@{@#{k0w~&#z=h_3EkkhEMYt zH~!nt$aFMs^M0mxdK{n-IR4_%zRg<=r5OcMjZMsq63vs1ER&2)QW8xkKQNNx1S$D+ zM5p4`WOifqdSAc81_EyDlg`fTnLO*lqFr}4Bu0N_Iwq$cD13X<-Tj+4KJbWPY!=8; z5zC3_eKvdMa`m&nU*E2(p6OP$Xa?JRl`Ep`ZhqCqJNynA-rlX6WByvUS8ICj6@JBy zMUN)6*ggNyF{8wPve#7pC#R15vRD~&>qcV0uLV|z+CGat)@6QH@3U<`+b`~m(bgGN zpMF_PJiWic@abz0&Kq$@`!=!c>A4>n8gXD=Z_C^bU%fio)`ozn2c*6gHDb4XT@Z^B?{KriKV61_ogu9qpW- zSCX1nvRT(ekP#eepma0Y&D0bal#^>sEkV={Qx|xEPG&JPL<%}PGkcJVdNUbDw#jqM M)YuG7fu=G5026B^yZ`_I diff --git a/v2/rscg_examples_site/static/sources/Aigamo.MatchGenerator.zip b/v2/rscg_examples_site/static/sources/Aigamo.MatchGenerator.zip new file mode 100644 index 0000000000000000000000000000000000000000..92272b96ead1dd135dd0351897ff54711fea0457 GIT binary patch literal 1740 zcmZuyc{tQt82&K^W60Fd$WmFdq|B5Omm6cOBTFMaveYFS+YF6|$#%1^;~^6_lAV&} zY7Ey>LSq?Xcw{L=4B}eGUaoYf`&{vdbN)H!Jm-6#^S$r;eaFfS#3u#-fFRJUkzhXt zX*^NO0{}jJ03gggH6;2G3|tA`YQA2?Lh1|RFbWnuBiN%YIG4gJi^kGViO3kFUx_I~ zdC;v9@AE{CK6Ep2>1|x6`hAw4634bYfNK+Bn!}^t+9un+7u4(C4_Pu&vm2c)gfuX_ z(@sA+W^XF&2IR^JdSADg`NO8Xc3AMmkZ6>X` zQIznx%L}rSH-@)#jbR4KIf8iDKOgD+x{PLrXsIl91KTh?3Q9o2(pgU{7s%y3oaI94 zbCzl#!}SM-0_8kpZvNUj76Yi&RY`sDeC(A{q);fqxsV7PTNN%)J|4k~P{{o%*dk59 zjNLY02PT3Bu`IKxAVmFd)A5J4NvMjRE?l{n{RZ<|>Ydrr`M^>?)o4ZXmb2Wn|GKs} zF~WJPpD7S9#xYdB>OW!Hd9~%DRt1QHw-p^iTFrLrv;;m;;)EWZUZiE`*_K3cNV7KgVXa!*83{=b|YQBFmu|T!svH%V2M6iy&rrG3zX=q5x<_?e5Pl=t0 zkq#ujs;YLbv~gUSe+a)TF%siMx)$K$>Z^9!H!A5I@eNAYkjzsD5{0b+3lABFO60qt z!iEBNJ3ip{6f{#MK2NDLS$;|=6;4KZG)fEZu#A&mW+5^3hQcyJEmZWB(&{p==qE9@ zsVYmxnZ>_0A5*S}pcVHIGsZPI1KEbzX&XsXW|xIFbckMC@hWM2K_ z@1>+?2Dv0dCt_~;doNdC$AH<-M>ryXfH6T9oU8F5foHWnWYkSA_9rir|!E`(N3 zaVlo=Bh~_!ZB6SmIy#P^ctqMEw7AaGMz-2xx_o6#cNaaSd@VfvNr5e@CKq{5w--=@ zsrV!&MtaBdlhC*GSFt(2XS#M9Hu=^>iJx@ix%u4i1|GG7bnQ-s6lF5%N?dw27kO0O z*V@TXA$h(D962Yr2r?Ks?_YbX06pRvUR^l-UGockk70MNw;a;tm>4d@rCf&L`x&+( zdE-e=1TMjT56p?pC|J~{$%s>ijU1XL&}*2BLzp8(a07iVK*XTzj*$QD4LI00Sqi0Mx@Y_>I%=_u6564WcEj^IEa4!nj^-NgLc1aI3 zzb!uk9tdS^D5d zF?)lZqX&h4cG-S7oq7EIHMTS{4r4SS7V-kxCO^({E4l+Ss<;=~xD*MxdE&W{qD)1z z{y3oG`Bw~%22N%3XL>{&4^hwHe{`qPc!163U~ko<-x!cv`~2q3S3iq7w58es zuO&(uz3=*?y4(@et+w*&(JN|`Wa>!AU@ew>9RWvsf>Rw!B?Hb4Y^)qowjYJpDx3F% zY~%xg8ROT3fz}=uzJsjHczDJBtKEZ}HkbH)