From bc584edc2d1769f7f551a6908483367d9341bbeb Mon Sep 17 00:00:00 2001 From: Andrei Ignat Date: Wed, 27 May 2026 06:41:44 +0300 Subject: [PATCH 1/6] first --- v2/RSCGExamplesData/GeneratorDataRec.json | 6 +++++ .../LinkDotNet.Enumeration/description.json | 22 ++++++++++++++++ .../LinkDotNet.Enumeration/src/EnumDemo.sln | 25 +++++++++++++++++++ .../src/EnumDemo/CarTypes.cs | 5 ++++ .../src/EnumDemo/EnumDemo.csproj | 22 ++++++++++++++++ .../src/EnumDemo/Program.cs | 20 +++++++++++++++ 6 files changed, 100 insertions(+) create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/description.json create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo.sln create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/CarTypes.cs create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/EnumDemo.csproj create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/Program.cs diff --git a/v2/RSCGExamplesData/GeneratorDataRec.json b/v2/RSCGExamplesData/GeneratorDataRec.json index 311a91f4e..8e6f2e9ec 100644 --- a/v2/RSCGExamplesData/GeneratorDataRec.json +++ b/v2/RSCGExamplesData/GeneratorDataRec.json @@ -1624,5 +1624,11 @@ "Category": 18, "dtStart": "2026-05-13T00:00:00", "show": true + }, + { + "ID": "LinkDotNet.Enumeration", + "Category": 19, + "dtStart": "2026-05-14T00:00:00", + "show": true } ] \ No newline at end of file diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/description.json b/v2/rscg_examples/LinkDotNet.Enumeration/description.json new file mode 100644 index 000000000..4049e2e19 --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/description.json @@ -0,0 +1,22 @@ +{ + "generator":{ + "name":"LinkDotNet.Enumeration", + "nuget":[ + "https://www.nuget.org/packages/LinkDotNet.Enumeration/" + ], + "link":"https://github.com/linkdotnet/Enumeration", + "author":"Steven Giesel", + "source":"https://github.com/linkdotnet/Enumeration" + }, + "data":{ + "goodFor":["Generating enumeration from classes in C# with matching"], + "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/LinkDotNet.Enumeration/src/EnumDemo.sln b/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo.sln new file mode 100644 index 000000000..ace1b5ec0 --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/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/LinkDotNet.Enumeration/src/EnumDemo/CarTypes.cs b/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/CarTypes.cs new file mode 100644 index 000000000..12065a5ac --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/CarTypes.cs @@ -0,0 +1,5 @@ +using LinkDotNet.Enumeration; +namespace EnumDemo; + +[Enumeration(Casing.Preserve,"None", "Dacia", "Tesla", "BMW", "Mercedes")] +public sealed partial record CarTypes; diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/EnumDemo.csproj b/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/EnumDemo.csproj new file mode 100644 index 000000000..bc7486c66 --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/EnumDemo.csproj @@ -0,0 +1,22 @@ + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + + diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/Program.cs b/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/Program.cs new file mode 100644 index 000000000..db3b964ac --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/src/EnumDemo/Program.cs @@ -0,0 +1,20 @@ +// See https://aka.ms/new-console-template for more information +using EnumDemo; +using System.Reflection; + +Console.WriteLine("Hello, World!"); +if(!CarTypes.TryParse("BMW", null,out var car)) +{ + Console.WriteLine("Invalid car type"); + return; +} + +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); From e16c9d5dbc117954f0b59dffefcc7485b1727515 Mon Sep 17 00:00:00 2001 From: Andrei Ignat Date: Wed, 27 May 2026 06:42:56 +0300 Subject: [PATCH 2/6] doc --- README.md | 30 +- later.md | 2 +- .../LinkDotNet.Enumeration/nuget.txt | 1 + .../LinkDotNet.Enumeration/readme.txt | 142 ++++ .../src/.tours/LinkDotNet.Enumeration.tour | 42 ++ .../LinkDotNet.Enumeration/video.json | 39 ++ .../docs/Authors/Steven_Giesel.md | 4 +- v2/rscg_examples_site/docs/Categories/Enum.md | 14 +- .../docs/Categories/_PrimitiveEnum.mdx | 12 +- .../RSCG-Examples/LinkDotNet.Enumeration.md | 636 ++++++++++++++++++ .../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 + 15 files changed, 928 insertions(+), 24 deletions(-) create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/nuget.txt create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/readme.txt create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/src/.tours/LinkDotNet.Enumeration.tour create mode 100644 v2/rscg_examples/LinkDotNet.Enumeration/video.json create mode 100644 v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md diff --git a/README.md b/README.md index 666dd3637..c6832f385 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# RSCG - 268 Examples of Roslyn Source Code Generators / 16 created by Microsoft / +# RSCG - 269 Examples of Roslyn Source Code Generators / 16 created by Microsoft / -The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 268 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 269 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 -## Latest Update : 2026-05-13 => 13 May 2026 +## Latest Update : 2026-05-14 => 14 May 2026 If you want to see examples with code, please click ***[List V2](https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG)*** @@ -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 268 Roslyn Source Code Generators that I have tested you can see and download source code example. +Those are the 269 Roslyn Source Code Generators that I have tested you can see and download source code example. ( including 16 from Microsoft ) +### 269. [LinkDotNet.Enumeration](https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration) , in the [Enum](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enum) category + +Generated on : 2026-05-14 => 14 May 2026 + +
+ Expand + + + +Author: Steven Giesel + +Source code generated enumeration with completeness! + +Nuget: [https://www.nuget.org/packages/LinkDotNet.Enumeration/](https://www.nuget.org/packages/LinkDotNet.Enumeration/) + + +Link: [https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration](https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration) + +Source: [https://github.com/linkdotnet/Enumeration](https://github.com/linkdotnet/Enumeration) + +
+ ### 268. [GenerateDispose](https://ignatandrei.github.io/RSCG_Examples/v2/docs/GenerateDispose) , in the [Disposer](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#disposer) category Generated on : 2026-05-13 => 13 May 2026 diff --git a/later.md b/later.md index c08220127..97905fcae 100644 --- a/later.md +++ b/later.md @@ -1,6 +1,6 @@ # Just later -## Latest Update : 2026-05-13 => 13 May 2026 +## Latest Update : 2026-05-14 => 14 May 2026 diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/nuget.txt b/v2/rscg_examples/LinkDotNet.Enumeration/nuget.txt new file mode 100644 index 000000000..a8e5e09b1 --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/nuget.txt @@ -0,0 +1 @@ +Source code generated enumeration with completeness! \ No newline at end of file diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/readme.txt b/v2/rscg_examples/LinkDotNet.Enumeration/readme.txt new file mode 100644 index 000000000..c4bd87e89 --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/readme.txt @@ -0,0 +1,142 @@ +# Enumeration + +[![.NET](https://github.com/linkdotnet/Enumeration/actions/workflows/dotnet.yml/badge.svg)](https://github.com/linkdotnet/Enumeration/actions/workflows/dotnet.yml) +[![Nuget](https://img.shields.io/nuget/dt/LinkDotNet.Enumeration)](https://www.nuget.org/packages/LinkDotNet.Enumeration/) +[![GitHub tag](https://img.shields.io/github/v/tag/linkdotnet/Enumeration?include_prereleases&logo=github&style=flat-square)](https://github.com/linkdotnet/Enumeration/releases) + +Source code generated string Enumeration with completeness! + +## What is in the box? + +This source code generator let's you easily create string based enumerations with a lot of features. + +```csharp +[Enumeration("Red", "Green", "Blue")] +public sealed partial record Color; +``` + +That's all you need to do to create a string based enumeration. You can either use it like this: + +```csharp +var color = Color.Red; + +// Create it by a string key: +var color = Color.Create("Red"); +``` + +## Exhaustiveness + +The great benefit of the library is that you have support for exhaustiveness: + + +```csharp + +var color = Color.Create("Red"); + +color.Match( + red => Console.WriteLine("It's red!"), + green => Console.WriteLine("It's green!"), + blue => Console.WriteLine("It's blue!") +); +``` + +Or return a value: + +```csharp +var color = Color.Create("Red"); + +var colorCode = color.Match( + red => "#FF0000", + green => "#00FF00", + blue => "#0000FF" +); +``` + +## More features! + +### Controlling field names + +The `Enumeration` attribute accepts an optional first argument of type `Casing` to control how the static member names are derived from the string values. By default, the library uses `PascalCase` to convert string values into member names. If you want to preserve the original casing of the string values, you can set the `Casing` to `Preserve`. + +```csharp +[Enumeration(Casing.Preserve, "red", "green", "blue")] +public sealed partial class Color; +``` + +Generates: + +```csharp +public sealed partial class Color +{ + public static readonly Color red = new("red"); + public static readonly Color green = new("green"); + public static readonly Color blue = new("blue"); + // ... +``` + +The default is `PascalCase` to feel "natural" to C# developers. + +### Creating from a string key + +Two methods are exposed `Create` and `TryCreate` to create an instance of the enumeration from a string key. The `Create` method will throw an `ArgumentException` if the key is not valid, while the `TryCreate` method will return a boolean indicating whether the creation was successful and output the created value through an out parameter. + +```csharp +var color = Color.Create("Red"); // Throws if "Red" is not a valid key + +if (Color.TryCreate("Red", out var color)) +{ + // Use color +} +else +{ + // Handle invalid key +} +``` + +### Parsing (IParsable) + +The generated types implement `IParsable` and `ISpanParsable`, making them compatible with modern .NET features like Minimal APIs and Model Binding. + +```csharp +if (Color.TryParse("Red", null, out var color)) +{ + // Use color +} +``` + +### Implicit/Explicit Conversions + +Instances of the generated enumeration can be implicitly converted to strings (returns the `Key` property), and strings can be explicitly converted back to the enumeration type (calls `Create`). + +```csharp +string colorKey = Color.Red; // Implicit conversion +var color = (Color)"Green"; // Explicit conversion +``` + +### Equality and Comparison + +Records implement value-based equality by default. For classes, `IEquatable` is automatically implemented, comparing the `Key` property. + +```csharp +var isRed = Color.Red == "Red"; // String comparison +var areEqual = Color.Red.Equals(Color.Create("Red")); // Value equality +``` + +### Getting all values + +Calling `All` will return a collection of all possible values. This is implemented using a `FrozenSet` to ensure immutability and thread-safety. + +## `JsonConverter` Generation + +The library allows via the `GenerateJsonConverter` property on the `Enumeration` attribute to generate a `JsonConverter` for the enumeration type. This converter will handle serialization and deserialization of the enumeration values as their string keys. + +```csharp +[Enumeration("Red", "Green", "Blue", GenerateJsonConverter = true)] +public sealed partial record Color; +``` + +This will generate a `JsonConverter` that can be used with `System.Text.Json` to serialize and deserialize `Color` instances as their string keys. The generated converter is called `{TypeName}JsonConverter`. + +### Limitations + +* Your code should run at least `net8.0` or later, as the library uses things like `FrozenSet`. diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/src/.tours/LinkDotNet.Enumeration.tour b/v2/rscg_examples/LinkDotNet.Enumeration/src/.tours/LinkDotNet.Enumeration.tour new file mode 100644 index 000000000..3c71f8147 --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/src/.tours/LinkDotNet.Enumeration.tour @@ -0,0 +1,42 @@ + +{ + "$schema": "https://aka.ms/codetour-schema", + "title": "LinkDotNet.Enumeration", + "steps": + [ + { + "file": "EnumDemo/EnumDemo.csproj", + "description": "First, we add Nuget [LinkDotNet.Enumeration](https://www.nuget.org/packages/LinkDotNet.Enumeration/) in csproj ", + "pattern": "LinkDotNet.Enumeration" + } + + ,{ + "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/LinkDotNet.Enumeration/LinkDotNet.Enumeration.EnumerationGenerator/EnumerationAttribute.g.cs", + "description": "Generated File 2 from 2 : EnumerationAttribute.g.cs ", + "line": 1 + } + + ,{ + "file": "EnumDemo/obj/GX/LinkDotNet.Enumeration/LinkDotNet.Enumeration.EnumerationGenerator/CarTypes.g.cs", + "description": "Generated File 1 from 2 : CarTypes.g.cs ", + "line": 1 + } + + ], + + "ref": "main" + +} \ No newline at end of file diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/video.json b/v2/rscg_examples/LinkDotNet.Enumeration/video.json new file mode 100644 index 000000000..86865d844 --- /dev/null +++ b/v2/rscg_examples/LinkDotNet.Enumeration/video.json @@ -0,0 +1,39 @@ +{ + "scriptName": "LinkDotNet.Enumeration", + "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 LinkDotNet.Enumeration . Generating enumeration from classes in C# with matching ."}, +{"typeStep":"browser","arg":"https://www.nuget.org/packages/LinkDotNet.Enumeration/"}, +{"typeStep":"text","arg": "The whole example is here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration"}, +{"typeStep":"text","arg": "You can download the code from here"}, +{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration#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\\LinkDotNet.Enumeration\\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\\LinkDotNet.Enumeration\\src"}, + +{"typeStep":"text","arg": "To use it ,you will put the Nuget LinkDotNet.Enumeration into the csproj "}, + +{"typeStep":"stepvscode","arg": "-r -g D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\LinkDotNet.Enumeration\\src\\EnumDemo\\EnumDemo.csproj"}, + +{"typeStep":"text","arg": "And now I will show you an example of using LinkDotNet.Enumeration"}, + +{"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/LinkDotNet.Enumeration#download-example-net--c-", +SpeakTest=" "}, +{"typeStep":"waitseconds","arg":"30"}, +] +} diff --git a/v2/rscg_examples_site/docs/Authors/Steven_Giesel.md b/v2/rscg_examples_site/docs/Authors/Steven_Giesel.md index 02c1707ad..344449349 100644 --- a/v2/rscg_examples_site/docs/Authors/Steven_Giesel.md +++ b/v2/rscg_examples_site/docs/Authors/Steven_Giesel.md @@ -1,7 +1,9 @@ # Author : Steven Giesel -Number RSCG: 1 +Number RSCG: 2 1 [BuildInfo](/docs/BuildInfo) [![Nuget](https://img.shields.io/nuget/dt/BuildInfo?label=BuildInfo)](https://www.nuget.org/packages/BuildInfo/) ![GitHub Repo stars](https://img.shields.io/github/stars/linkdotnet/BuildInformation?style=social) 2024-01-20 + 2 [LinkDotNet.Enumeration](/docs/LinkDotNet.Enumeration) [![Nuget](https://img.shields.io/nuget/dt/LinkDotNet.Enumeration?label=LinkDotNet.Enumeration)](https://www.nuget.org/packages/LinkDotNet.Enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/linkdotnet/Enumeration?style=social) 2026-05-14 + diff --git a/v2/rscg_examples_site/docs/Categories/Enum.md b/v2/rscg_examples_site/docs/Categories/Enum.md index 01d77f115..64c9feed6 100644 --- a/v2/rscg_examples_site/docs/Categories/Enum.md +++ b/v2/rscg_examples_site/docs/Categories/Enum.md @@ -1,6 +1,6 @@

Enum

-Number RSCG: 14 +Number RSCG: 15 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-08 @@ -20,13 +20,15 @@ Number RSCG: 14 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 [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 + 10 [LinkDotNet.Enumeration](/docs/LinkDotNet.Enumeration) [![Nuget](https://img.shields.io/nuget/dt/LinkDotNet.Enumeration?label=LinkDotNet.Enumeration)](https://www.nuget.org/packages/LinkDotNet.Enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/linkdotnet/Enumeration?style=social) 2026-05-14 - 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 + 11 [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 - 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 + 12 [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 - 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 + 13 [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 - 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 + 14 [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 + + 15 [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 6a65a15e1..a712a7d88 100644 --- a/v2/rscg_examples_site/docs/Categories/_PrimitiveEnum.mdx +++ b/v2/rscg_examples_site/docs/Categories/_PrimitiveEnum.mdx @@ -18,15 +18,17 @@ 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 [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 + 10 [LinkDotNet.Enumeration](/docs/LinkDotNet.Enumeration) [![Nuget](https://img.shields.io/nuget/dt/LinkDotNet.Enumeration?label=LinkDotNet.Enumeration)](https://www.nuget.org/packages/LinkDotNet.Enumeration/) ![GitHub Repo stars](https://img.shields.io/github/stars/linkdotnet/Enumeration?style=social) 2026-05-14 - 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 + 11 [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 - 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 + 12 [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 - 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 + 13 [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 - 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 + 14 [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 + + 15 [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/LinkDotNet.Enumeration.md b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md new file mode 100644 index 000000000..8f4eb76b0 --- /dev/null +++ b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md @@ -0,0 +1,636 @@ +--- +sidebar_position: 2690 +title: 269 - LinkDotNet.Enumeration +description: Generating enumeration from classes in C# with matching +slug: /LinkDotNet.Enumeration +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import TOCInline from '@theme/TOCInline'; +import SameCategory from '../Categories/_PrimitiveEnum.mdx'; + +# LinkDotNet.Enumeration by Steven Giesel + + + + +## NuGet / site data +[![Nuget](https://img.shields.io/nuget/dt/LinkDotNet.Enumeration?label=LinkDotNet.Enumeration)](https://www.nuget.org/packages/LinkDotNet.Enumeration/) +[![GitHub last commit](https://img.shields.io/github/last-commit/linkdotnet/Enumeration?label=updated)](https://github.com/linkdotnet/Enumeration) +![GitHub Repo stars](https://img.shields.io/github/stars/linkdotnet/Enumeration?style=social) + +## Details + +### Info +:::info + +Name: **LinkDotNet.Enumeration** + +Source code generated enumeration with completeness! + +Author: Steven Giesel + +NuGet: +*https://www.nuget.org/packages/LinkDotNet.Enumeration/* + + +You can find more details at https://github.com/linkdotnet/Enumeration + +Source: https://github.com/linkdotnet/Enumeration + +::: + +### Author +:::note +Steven Giesel +![Alt text](https://github.com/linkdotnet.png) +::: + +## Original Readme +:::note + +# Enumeration + +[![.NET](https://github.com/linkdotnet/Enumeration/actions/workflows/dotnet.yml/badge.svg)](https://github.com/linkdotnet/Enumeration/actions/workflows/dotnet.yml) +[![Nuget](https://img.shields.io/nuget/dt/LinkDotNet.Enumeration)](https://www.nuget.org/packages/LinkDotNet.Enumeration/) +[![GitHub tag](https://img.shields.io/github/v/tag/linkdotnet/Enumeration?include_prereleases&logo=github&style=flat-square)](https://github.com/linkdotnet/Enumeration/releases) + +Source code generated string Enumeration with completeness! + +## What is in the box? + +This source code generator let's you easily create string based enumerations with a lot of features. + +```csharp +[Enumeration("Red", "Green", "Blue")] +public sealed partial record Color; +``` + +That's all you need to do to create a string based enumeration. You can either use it like this: + +```csharp +var color = Color.Red; + +// Create it by a string key: +var color = Color.Create("Red"); +``` + +## Exhaustiveness + +The great benefit of the library is that you have support for exhaustiveness: + + +```csharp + +var color = Color.Create("Red"); + +color.Match( + red => Console.WriteLine("It's red!"), + green => Console.WriteLine("It's green!"), + blue => Console.WriteLine("It's blue!") +); +``` + +Or return a value: + +```csharp +var color = Color.Create("Red"); + +var colorCode = color.Match( + red => "#FF0000", + green => "#00FF00", + blue => "#0000FF" +); +``` + +## More features! + +### Controlling field names + +The `Enumeration` attribute accepts an optional first argument of type `Casing` to control how the static member names are derived from the string values. By default, the library uses `PascalCase` to convert string values into member names. If you want to preserve the original casing of the string values, you can set the `Casing` to `Preserve`. + +```csharp +[Enumeration(Casing.Preserve, "red", "green", "blue")] +public sealed partial class Color; +``` + +Generates: + +```csharp +public sealed partial class Color +{ + public static readonly Color red = new("red"); + public static readonly Color green = new("green"); + public static readonly Color blue = new("blue"); + // ... +``` + +The default is `PascalCase` to feel "natural" to C# developers. + +### Creating from a string key + +Two methods are exposed `Create` and `TryCreate` to create an instance of the enumeration from a string key. The `Create` method will throw an `ArgumentException` if the key is not valid, while the `TryCreate` method will return a boolean indicating whether the creation was successful and output the created value through an out parameter. + +```csharp +var color = Color.Create("Red"); // Throws if "Red" is not a valid key + +if (Color.TryCreate("Red", out var color)) +{ + // Use color +} +else +{ + // Handle invalid key +} +``` + +### Parsing (IParsable) + +The generated types implement `IParsable` and `ISpanParsable`, making them compatible with modern .NET features like Minimal APIs and Model Binding. + +```csharp +if (Color.TryParse("Red", null, out var color)) +{ + // Use color +} +``` + +### Implicit/Explicit Conversions + +Instances of the generated enumeration can be implicitly converted to strings (returns the `Key` property), and strings can be explicitly converted back to the enumeration type (calls `Create`). + +```csharp +string colorKey = Color.Red; // Implicit conversion +var color = (Color)"Green"; // Explicit conversion +``` + +### Equality and Comparison + +Records implement value-based equality by default. For classes, `IEquatable` is automatically implemented, comparing the `Key` property. + +```csharp +var isRed = Color.Red == "Red"; // String comparison +var areEqual = Color.Red.Equals(Color.Create("Red")); // Value equality +``` + +### Getting all values + +Calling `All` will return a collection of all possible values. This is implemented using a `FrozenSet` to ensure immutability and thread-safety. + +## `JsonConverter` Generation + +The library allows via the `GenerateJsonConverter` property on the `Enumeration` attribute to generate a `JsonConverter` for the enumeration type. This converter will handle serialization and deserialization of the enumeration values as their string keys. + +```csharp +[Enumeration("Red", "Green", "Blue", GenerateJsonConverter = true)] +public sealed partial record Color; +``` + +This will generate a `JsonConverter` that can be used with `System.Text.Json` to serialize and deserialize `Color` instances as their string keys. The generated converter is called `\{TypeName}\}JsonConverter`. + +### Limitations + +* Your code should run at least `net8.0` or later, as the library uses things like `FrozenSet`. + + +::: + +### About +:::note + +Generating enumeration from classes in C# with matching + + +::: + +## How to use + +### Example (source csproj, source files) + + + + + +This is the CSharp Project that references **LinkDotNet.Enumeration** +```xml showLineNumbers {16} + + + + Exe + net10.0 + enable + enable + + + + true + $(BaseIntermediateOutputPath)\GX + + + + + + + + + + + +``` + + + + + + This is the use of **LinkDotNet.Enumeration** in *Program.cs* + +```csharp showLineNumbers +// See https://aka.ms/new-console-template for more information +using EnumDemo; +using System.Reflection; + +Console.WriteLine("Hello, World!"); +if(!CarTypes.TryParse("BMW", null,out var car)) +{ + Console.WriteLine("Invalid car type"); + return; +} + +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); + +``` + + + + + This is the use of **LinkDotNet.Enumeration** in *CarTypes.cs* + +```csharp showLineNumbers +using LinkDotNet.Enumeration; +namespace EnumDemo; + +[Enumeration(Casing.Preserve,"None", "Dacia", "Tesla", "BMW", "Mercedes")] +public sealed partial record CarTypes; + +``` + + + + +### Generated Files + +Those are taken from $(BaseIntermediateOutputPath)\GX + + + + +```csharp showLineNumbers +// +#nullable enable + +using System; +using System.Collections.Frozen; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace EnumDemo; + +[DebuggerDisplay("{Key}")] +public sealed partial record CarTypes : IParsable, ISpanParsable, ISpanFormattable +{ + /// Gets the string key that identifies this enumeration value. + public string Key \{ get; init; \} = default!; + + private CarTypes(string key) + { + ArgumentException.ThrowIfNullOrWhiteSpace(key); + Key = key; + } + + /// Gets the instance for None. + public static readonly CarTypes None = new("None"); + /// Gets the instance for Dacia. + public static readonly CarTypes Dacia = new("Dacia"); + /// Gets the instance for Tesla. + public static readonly CarTypes Tesla = new("Tesla"); + /// Gets the instance for BMW. + public static readonly CarTypes BMW = new("BMW"); + /// Gets the instance for Mercedes. + public static readonly CarTypes Mercedes = new("Mercedes"); + + /// Gets a frozen set of all valid instances. Ordering is not guaranteed. + public static FrozenSet All \{ get; \} = + new CarTypes[] \{ None, Dacia, Tesla, BMW, Mercedes }.ToFrozenSet(); + + /// Creates the instance matching . + /// The key to look up. Must not be null, empty, or whitespace. + /// The matching instance. + /// Thrown when is null, empty, or whitespace. + /// Thrown when does not match any known value. + public static CarTypes Create(string key) + { + ArgumentException.ThrowIfNullOrWhiteSpace(key); + return key switch + { + "None" => None, + "Dacia" => Dacia, + "Tesla" => Tesla, + "BMW" => BMW, + "Mercedes" => Mercedes, + _ => throw new InvalidOperationException($"{key} is not a valid value for CarTypes") + }; + } + + /// Tries to create the instance matching . + /// The key to look up. + /// When this method returns , contains the matching instance; otherwise . + /// if a matching instance was found; otherwise . + public static bool TryCreate(string? key, [NotNullWhen(true)] out CarTypes? value) + { + value = key switch + { + "None" => None, + "Dacia" => Dacia, + "Tesla" => Tesla, + "BMW" => BMW, + "Mercedes" => Mercedes, + _ => null + }; + return value is not null; + } + + /// Tries to create the instance matching without allocating a string. + /// The key span to look up. + /// When this method returns , contains the matching instance; otherwise . + /// if a matching instance was found; otherwise . + public static bool TryCreate(ReadOnlySpan key, [NotNullWhen(true)] out CarTypes? value) + { + value = key switch + { + "None" => None, + "Dacia" => Dacia, + "Tesla" => Tesla, + "BMW" => BMW, + "Mercedes" => Mercedes, + _ => null + }; + return value is not null; + } + + /// Returns if is a valid enumeration value. + /// The key to check. + /// if the key is defined; otherwise . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsDefined(string? key) => TryCreate(key, out _); + + /// Returns if is a valid enumeration value without allocating a string. + /// The key span to check. + /// if the key is defined; otherwise . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsDefined(ReadOnlySpan key) => TryCreate(key, out _); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static CarTypes Parse(string s, IFormatProvider? provider) => Create(s); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryParse(string? s, IFormatProvider? provider, [NotNullWhen(true)] out CarTypes? result) => TryCreate(s, out result); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static CarTypes Parse(ReadOnlySpan s, IFormatProvider? provider) => Create(s.ToString()); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [NotNullWhen(true)] out CarTypes? result) => TryCreate(s, out result); + + /// Returns when 's key equals using ordinal string comparison. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(CarTypes? a, string? b) + => a is not null && b is not null && a.Key.Equals(b, StringComparison.Ordinal); + + /// Returns when 's key does not equal . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(CarTypes? a, string? b) => !(a == b); + + /// Implicitly converts the instance to its . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator string(CarTypes value) => value.Key; + + /// Explicitly converts the to a instance. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator CarTypes(string key) => Create(key); + + /// Returns the key of this enumeration value. + /// The string. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override string ToString() => Key; + + /// + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + if (Key.AsSpan().TryCopyTo(destination)) + { + charsWritten = Key.Length; + return true; + } + charsWritten = 0; + return false; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string ToString(string? format, IFormatProvider? provider) => Key; + + /// Returns the value corresponding to the current enumeration value. + /// Returned when the current value is . + /// Returned when the current value is . + /// Returned when the current value is . + /// Returned when the current value is . + /// Returned when the current value is . + /// The return type. + /// The matched value. + /// Thrown when no case matches. + public T Match(T onNone, T onDacia, T onTesla, T onBMW, T onMercedes) + { + return Key switch + { + "None" => onNone, + "Dacia" => onDacia, + "Tesla" => onTesla, + "BMW" => onBMW, + "Mercedes" => onMercedes, + _ => throw new InvalidOperationException($"Unhandled enumeration value: {Key}") + }; + } + + /// Invokes the function corresponding to the current value and returns its result. + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// The return type. + /// The value returned by the matched function. + /// Thrown when no case matches. + public T Match(Func onNone, Func onDacia, Func onTesla, Func onBMW, Func onMercedes) + { + return Key switch + { + "None" => onNone(), + "Dacia" => onDacia(), + "Tesla" => onTesla(), + "BMW" => onBMW(), + "Mercedes" => onMercedes(), + _ => throw new InvalidOperationException($"Unhandled enumeration value: {Key}") + }; + } + + /// Invokes the function corresponding to the current value, passing , and returns its result. + /// The state to pass to the function. + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// The return type. + /// The type of the state object. + /// The value returned by the matched function. + /// Thrown when no case matches. + public T Match(TState state, Func onNone, Func onDacia, Func onTesla, Func onBMW, Func onMercedes) + { + return Key switch + { + "None" => onNone(state), + "Dacia" => onDacia(state), + "Tesla" => onTesla(state), + "BMW" => onBMW(state), + "Mercedes" => onMercedes(state), + _ => throw new InvalidOperationException($"Unhandled enumeration value: {Key}") + }; + } + + /// Invokes the action corresponding to the current value. + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Thrown when no case matches. + public void Match(Action onNone, Action onDacia, Action onTesla, Action onBMW, Action onMercedes) + { + switch (Key) + { + case "None": onNone(); return; + case "Dacia": onDacia(); return; + case "Tesla": onTesla(); return; + case "BMW": onBMW(); return; + case "Mercedes": onMercedes(); return; + default: throw new InvalidOperationException($"Unhandled enumeration value: {Key}"); + } + } + + /// Invokes the action corresponding to the current value, passing . + /// The state to pass to the action. + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// Invoked when the current value is . + /// The type of the state object. + /// Thrown when no case matches. + public void Match(TState state, Action onNone, Action onDacia, Action onTesla, Action onBMW, Action onMercedes) + { + switch (Key) + { + case "None": onNone(state); return; + case "Dacia": onDacia(state); return; + case "Tesla": onTesla(state); return; + case "BMW": onBMW(state); return; + case "Mercedes": onMercedes(state); return; + default: throw new InvalidOperationException($"Unhandled enumeration value: {Key}"); + } + } +} + +``` + + + + +```csharp showLineNumbers +// +#nullable enable + +using System; + +namespace LinkDotNet.Enumeration; + +/// Specifies how static member names are derived from the string values. +internal enum Casing +{ + /// Converts each value to PascalCase (default). + PascalCase, + /// Uses the raw string value as the member name. + Preserve +} + +/// +/// Marks a partial class or partial record as a source-generated enumeration. +/// The generator emits: Key property, private constructor, static readonly fields, +/// All, Create, TryCreate, == / != operators, ToString, Match<T> and Match(Action). +/// +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +internal sealed class EnumerationAttribute : Attribute +{ + public string[] Values \{ get; } + public Casing MemberCasing \{ get; } + /// + /// When , a + /// is applied to the enumeration type and a \{TypeName}\}JsonConverter class is generated + /// that serializes and deserializes the type as its Key string using + /// . + /// + public bool GenerateJsonConverter \{ get; init; } + public EnumerationAttribute(params string[] values) => (Values, MemberCasing) = (values, Casing.PascalCase); + public EnumerationAttribute(Casing casing, params string[] values) => (Values, MemberCasing) = (values, casing); +} +``` + + + + +## Useful + +### Download Example (.NET C#) + +:::tip + +[Download Example project LinkDotNet.Enumeration ](/sources/LinkDotNet.Enumeration.zip) + +::: + + +### Share LinkDotNet.Enumeration + + + +https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration + + + diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/index.md b/v2/rscg_examples_site/docs/RSCG-Examples/index.md index 2f09c0b34..86901ae2d 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: 268 RSCG list by category -description: 268 RSCG list by category +title: 269 RSCG list by category +description: 269 RSCG list by category slug: /rscg-examples --- @@ -817,7 +817,7 @@ import DocCardList from '@theme/DocCardList'; ## Enum
- Expand Enum =>examples:14 + Expand Enum =>examples:15 @@ -888,6 +888,11 @@ import DocCardList from '@theme/DocCardList'; [Aigamo.MatchGenerator](/docs/Aigamo.MatchGenerator) + + + +[LinkDotNet.Enumeration](/docs/LinkDotNet.Enumeration) +
@@ -1972,6 +1977,8 @@ flowchart LR; Enum--> Aigamo.MatchGenerator((Aigamo.MatchGenerator)) + Enum--> LinkDotNet.Enumeration((LinkDotNet.Enumeration)) + 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 043aecbc0..f54fb1847 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 268 Roslyn Source Code Generator (RSCG) +of 269 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 fb5277db4..8aed8801a 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'; -## 268 RSCG with examples in descending chronological order +## 269 RSCG with examples in descending chronological order -This is the list of 268 ( 16 from Microsoft) RSCG with examples +This is the list of 269 ( 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 268 ( 16 from Microsoft) RSCG with examples | No | Name | Date | Category | | --------- | ----- | ---- | -------- | +|269| [LinkDotNet.Enumeration by Steven Giesel ](/docs/LinkDotNet.Enumeration)|2026-05-14 => 14 May 2026 | [Enum](/docs/Categories/Enum) | |268| [GenerateDispose by Itai Tzur ](/docs/GenerateDispose)|2026-05-13 => 13 May 2026 | [Disposer](/docs/Categories/Disposer) | |267| [Maestria.TypeProviders by Fábio Monteiro Naspolini ](/docs/Maestria.TypeProviders)|2026-04-09 => 09 April 2026 | [FilesToCode](/docs/Categories/FilesToCode) | |266| [Aigamo.MatchGenerator by Aigamo ](/docs/Aigamo.MatchGenerator)|2026-04-08 => 08 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 3b511c31e..984a353de 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: '268 Examples (16 from MSFT)', +title: '269 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 fbf36bac9..095f0f55e 100644 --- a/v2/rscg_examples_site/static/exports/RSCG.json +++ b/v2/rscg_examples_site/static/exports/RSCG.json @@ -2145,6 +2145,14 @@ "Source": "https://github.com/ItaiTzur76/GenerateDispose", "Category": "Disposer", "AddedOn": "2026-05-13T00:00:00" + }, + { + "Name": "LinkDotNet.Enumeration", + "Link": "https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration", + "NuGet": "https://www.nuget.org/packages/LinkDotNet.Enumeration/", + "Source": "https://github.com/linkdotnet/Enumeration", + "Category": "Enum", + "AddedOn": "2026-05-14T00:00:00" } ] } \ No newline at end of file From c2d0a0a0a40956b3c75ed8d8075ac27979218a71 Mon Sep 17 00:00:00 2001 From: Andrei Ignat Date: Wed, 27 May 2026 06:44:37 +0300 Subject: [PATCH 3/6] zip --- v2/book/examples/LinkDotNet.Enumeration.html | 64 ++++++++++++++++++ v2/book/list.html | 6 +- v2/book/pandocHTML.yaml | 1 + v2/docFind.json | 6 ++ .../static/sources/LinkDotNet.Enumeration.zip | Bin 0 -> 1645 bytes 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 v2/book/examples/LinkDotNet.Enumeration.html create mode 100644 v2/rscg_examples_site/static/sources/LinkDotNet.Enumeration.zip diff --git a/v2/book/examples/LinkDotNet.Enumeration.html b/v2/book/examples/LinkDotNet.Enumeration.html new file mode 100644 index 000000000..8aafe2698 --- /dev/null +++ b/v2/book/examples/LinkDotNet.Enumeration.html @@ -0,0 +1,64 @@ + +

RSCG nr 269 : LinkDotNet.Enumeration

+ +

Info

+Nuget : https://www.nuget.org/packages/LinkDotNet.Enumeration/ + +

You can find more details at : https://github.com/linkdotnet/Enumeration

+ +

Author :Steven Giesel

+ +

Source: https://github.com/linkdotnet/Enumeration

+ +

About

+ +Generating enumeration from classes in C# with matching + +

+ How to use +

+

+ Add reference to the LinkDotNet.Enumeration 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 CarTypes.g.cs +
+ + +
+ The file generated is EnumerationAttribute.g.cs +
+ + +

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

+ + +

+ 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 31776b1e1..5c6342aa6 100644 --- a/v2/book/list.html +++ b/v2/book/list.html @@ -17,7 +17,7 @@

-This is the list of 268 RSCG with examples => +This is the list of 269 RSCG with examples =>

@@ -1098,6 +1098,10 @@

+ + + +
268 GenerateDispose
269LinkDotNet.Enumeration
diff --git a/v2/book/pandocHTML.yaml b/v2/book/pandocHTML.yaml index 43dbd53d3..fce328a0c 100644 --- a/v2/book/pandocHTML.yaml +++ b/v2/book/pandocHTML.yaml @@ -282,6 +282,7 @@ input-files: - examples/Aigamo.MatchGenerator.html - examples/Maestria.TypeProviders.html - examples/GenerateDispose.html +- examples/LinkDotNet.Enumeration.html # or you may use input-file: with a single value # defaults: diff --git a/v2/docFind.json b/v2/docFind.json index 801e7ba77..03b462871 100644 --- a/v2/docFind.json +++ b/v2/docFind.json @@ -1606,5 +1606,11 @@ "category": "Disposer", "href": "/RSCG_Examples/v2/docs/GenerateDispose/", "body": "A Rosyln-powered generator for the Dispose-pattern\u0027s boilerplate code." + }, + { + "title": "LinkDotNet.Enumeration", + "category": "Enum", + "href": "/RSCG_Examples/v2/docs/LinkDotNet.Enumeration/", + "body": "Source code generated enumeration with completeness!" } ] \ No newline at end of file diff --git a/v2/rscg_examples_site/static/sources/LinkDotNet.Enumeration.zip b/v2/rscg_examples_site/static/sources/LinkDotNet.Enumeration.zip new file mode 100644 index 0000000000000000000000000000000000000000..e9af2c4ad231ec8124063530349a0ca618ea71ab GIT binary patch literal 1645 zcmWIWW@Zs#U|`^2@L1FybD#5o{7yy&h5{A_1|FcOYhG!tOKNVuUU5#|(#ae1ZW{=+ zJ?FS!&GBjylcJ;77FAwZmzh58%M7x%1dHEX#49!>!z1P5fv=NGUnoBn^*TCH*g8+Z z;`ZIY#~&a6zht+4eeHWUy{Nk{mvZhqd2X8449RFu*)v-A9RFy{}x@>DrAdr7YPv+hh0J8T58- zmA;idJ7>}|m8B9NOnMn4Kl3cnkZWcVS6TRzuX~;Mep)TQJKo2b~0pY+RHU>s@9Zhx2cu?N>X}O_SHH+uQ}=0)syU%_dmF51eQJW zJRNw{)N%uJPkIFZ4gG+Z=WLEv%~k)!w|8Q3~Q#VTa=*ss`7O(mCGd-5``oYis#@}Xf-_Tc{<#%rBq-SO7b7Ou9 z#79S3Ryr%WX!=U*`2Wzu&)`JRJO(qbM>RH17T%BFdN$M^{r-ca{*o;8j) zx6k;ib^6ht>$gnin7?uqP~;C;^__2(($!67a}r&)*xx8$E+gxb>=bg_JF?|zR_`*7 zZ8J1Bs2rZga_h7U@97^r9j{-DBm7VZ^g~SQuWmJ9GIe2MV30ue1I#l(KNJ+@XSD{| z`X4qBm>a$Fzhaj}g6E}1-H!}QLRC0Kw{$cfRk@xdbo=5{ofrAZ57a-3Z*UIr3Q5>d z^8McB-TL)=_8#ZHaz0=}d30E3y(-t0wQ<1{mY+W0WH-A%wCfif%J_$1C!E{}i|J$qvR@iqk(V+L*+ZA;lUf!`B%%|Ku{U)&-&3SC*wN_>r93 z%U+;=&NtS&PW?7x?CFOao;Nr5xD{%#&dt8rAyvS~H9>fa@$9WV7b5Q4v&=o1_%2(T z+t2^aiyuAPCulNF3ED?0eyl^{u*JPP<4p{wbWss;{-LQ96RTN$bGrkigkO zLjQwSymAWW6IpV~Biu9NX?1zST3(@gsX1&D-?#o{`@U8-X+HNZw>#@Meo#k*?N4CX zmejrvQ~-u8BQR`*k;68iC_lX@F&7xLr5C)jfWgZ4VDG{585OC`$?tqew}UIzI~r%%3Ll)-ku#g@3D2-p(m62 zPDgnzw$Rn>oVQptV=CK16UNDTniq^z4<{J-yn7hOm*nkqH->BX#T~sjwYSd6(vMZ= zFviwJ>OwdACMk&(@Dg&AVi(jUrbb7r%1s;O<3TK@*stuawe} z32^SU@;vlFndd;S_QU>94RcK8no29{f8NX5)cmdd*O%*`BAa>++8(_1c#T7J`Nxx5 zFZ<#g=N$MYrgYnoId5NQ@|3s(V%crRmwvoz;ksmMnv&)>M_RZxY*L!fu179jMm2Ry zzFvKiGO2#wpFctO|FH&mGct*QGZ*$!6&R{W0G?)nWh}BzY?&3I?J+QlU^ Date: Wed, 27 May 2026 06:59:40 +0300 Subject: [PATCH 4/6] modre docs --- .../GenerateDispose/description.json | 45 +++++- v2/rscg_examples/GenerateDispose/video.json | 2 +- .../LinkDotNet.Enumeration/description.json | 22 ++- .../LinkDotNet.Enumeration/video.json | 2 +- .../docs/RSCG-Examples/GenerateDispose.md | 133 +++++++++++++++++- .../RSCG-Examples/LinkDotNet.Enumeration.md | 85 +++++++++-- .../static/exports/RSCG.xlsx | Bin 14123 -> 14164 bytes 7 files changed, 269 insertions(+), 20 deletions(-) diff --git a/v2/rscg_examples/GenerateDispose/description.json b/v2/rscg_examples/GenerateDispose/description.json index efbb168a3..d5e4e83a8 100644 --- a/v2/rscg_examples/GenerateDispose/description.json +++ b/v2/rscg_examples/GenerateDispose/description.json @@ -9,7 +9,50 @@ "source":"https://github.com/ItaiTzur76/GenerateDispose" }, "data":{ - "goodFor":["Generating the Dispose method for a class that implements IDisposable."], + "goodFor":["## Summary: GenerateDispose", +"### Purpose", +"A Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute.", +"It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).", +"", +"### How to Define", +"[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))]", +"partial class DALDB : IDisposable // : IDisposable is optional!", +"{", +" private ConnectionDB cn;", +" private ConnectionDB cn1;", +"", +" public DALDB()", +" {", +" cn = new ConnectionDB();", +" cn1 = new ConnectionDB();", +" }", +"", +" public void Drop() // Your custom disposal logic", +" {", +" cn.Dispose();", +" cn1.Dispose();", +" }", +"}", +"", +"- The class must be partial", +"- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments", +"", +"### What Gets Generated", +"- public void Dispose() (thread-safe, calls your method)", +"- A private int _isDisposed field for double-dispose protection", +"- Adapts to sealed vs non-sealed automatically (private vs protected virtual)", +"", +"### How to Use", +"using (var db = new DALDB())", +"{", +" // use db...", +"} // Dispose() called automatically", +"", +"### Key Benefits", +"- 10+ lines of boilerplate replaced by 1 attribute", +"- sealed changes auto-adapt the Dispose pattern", +"- No manual IDisposable wiring needed", +""], "csprojDemo":"IDisp.csproj", "csFiles":["Program.cs","DALDB.cs","ConnectionDB.cs"], "excludeDirectoryGenerated":[""], diff --git a/v2/rscg_examples/GenerateDispose/video.json b/v2/rscg_examples/GenerateDispose/video.json index 06510cbcc..a2a68d84f 100644 --- a/v2/rscg_examples/GenerateDispose/video.json +++ b/v2/rscg_examples/GenerateDispose/video.json @@ -8,7 +8,7 @@ {"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 GenerateDispose . Generating the Dispose method for a class that implements IDisposable. ."}, +{"typeStep":"text","arg": "Today I will present GenerateDispose . ## Summary: GenerateDispose### PurposeA Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute.It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).### How to Define[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))]partial class DALDB : IDisposable // : IDisposable is optional!{ private ConnectionDB cn; private ConnectionDB cn1; public DALDB() { cn = new ConnectionDB(); cn1 = new ConnectionDB(); } public void Drop() // Your custom disposal logic { cn.Dispose(); cn1.Dispose(); }}- The class must be partial- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments### What Gets Generated- public void Dispose() (thread-safe, calls your method)- A private int _isDisposed field for double-dispose protection- Adapts to sealed vs non-sealed automatically (private vs protected virtual)### How to Useusing (var db = new DALDB()){ // use db...} // Dispose() called automatically### Key Benefits- 10+ lines of boilerplate replaced by 1 attribute- sealed changes auto-adapt the Dispose pattern- No manual IDisposable wiring needed ."}, {"typeStep":"browser","arg":"https://www.nuget.org/packages/GenerateDispose/"}, {"typeStep":"text","arg": "The whole example is here"}, {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/GenerateDispose"}, diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/description.json b/v2/rscg_examples/LinkDotNet.Enumeration/description.json index 4049e2e19..992ad7769 100644 --- a/v2/rscg_examples/LinkDotNet.Enumeration/description.json +++ b/v2/rscg_examples/LinkDotNet.Enumeration/description.json @@ -9,7 +9,27 @@ "source":"https://github.com/linkdotnet/Enumeration" }, "data":{ - "goodFor":["Generating enumeration from classes in C# with matching"], + "goodFor":["## Summary: LinkDotNet.Enumeration", +"", +"### Purpose", +"A source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns.", +"", +"### How to Define", +"[Enumeration(Casing.Preserve, \"None\", \"Dacia\", \"Tesla\", \"BMW\", \"Mercedes\")]", +"public sealed partial record CarTypes;", +"", +"### How to Use", +"CarTypes.TryParse(\"BMW\", null, out var car);", +"car.Match(onBMW: () => \"this is bmw\", onDacia: () => \"this is dacia\", ...);", +"", +"### Key Features", +"- Exhaustive matching: Match() requires all values", +"- Create / TryCreate: throws vs returns bool", +"- IParsable: Minimal APIs & Model Binding", +"- Implicit string conversion", +"- CarTypes.All returns FrozenSet", +"- JSON: GenerateJsonConverter = true" +], "csprojDemo":"EnumDemo.csproj", "csFiles":["Program.cs","CarTypes.cs"], "excludeDirectoryGenerated":[""], diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/video.json b/v2/rscg_examples/LinkDotNet.Enumeration/video.json index 86865d844..c25419d34 100644 --- a/v2/rscg_examples/LinkDotNet.Enumeration/video.json +++ b/v2/rscg_examples/LinkDotNet.Enumeration/video.json @@ -8,7 +8,7 @@ {"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 LinkDotNet.Enumeration . Generating enumeration from classes in C# with matching ."}, +{"typeStep":"text","arg": "Today I will present LinkDotNet.Enumeration . ## Summary: LinkDotNet.Enumeration### PurposeA source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns.### How to Define[Enumeration(Casing.Preserve, "None", "Dacia", "Tesla", "BMW", "Mercedes")]public sealed partial record CarTypes;### How to UseCarTypes.TryParse("BMW", null, out var car);car.Match(onBMW: () => "this is bmw", onDacia: () => "this is dacia", ...);### Key Features- Exhaustive matching: Match() requires all values- Create / TryCreate: throws vs returns bool- IParsable<T>: Minimal APIs & Model Binding- Implicit string conversion- CarTypes.All returns FrozenSet<CarTypes>- JSON: GenerateJsonConverter = true ."}, {"typeStep":"browser","arg":"https://www.nuget.org/packages/LinkDotNet.Enumeration/"}, {"typeStep":"text","arg": "The whole example is here"}, {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration"}, diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md b/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md index c8ace5a38..3c1b619a0 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md @@ -1,7 +1,7 @@ --- sidebar_position: 2680 title: 268 - GenerateDispose -description: Generating the Dispose method for a class that implements IDisposable. +description: ## Summary: GenerateDispose slug: /GenerateDispose --- import Tabs from '@theme/Tabs'; @@ -163,7 +163,136 @@ Happy coding! ### About :::note -Generating the Dispose method for a class that implements IDisposable. +## Summary: GenerateDispose + + +### Purpose + + +A Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute. + + +It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed). + + + + + +### How to Define + + +[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))] + + +partial class DALDB : IDisposable // : IDisposable is optional! + + +{ + + + private ConnectionDB cn; + + + private ConnectionDB cn1; + + + + + + public DALDB() + + + { + + + cn = new ConnectionDB(); + + + cn1 = new ConnectionDB(); + + + } + + + + + + public void Drop() // Your custom disposal logic + + + { + + + cn.Dispose(); + + + cn1.Dispose(); + + + } + + +} + + + + + +- The class must be partial + + +- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments + + + + + +### What Gets Generated + + +- public void Dispose() (thread-safe, calls your method) + + +- A private int _isDisposed field for double-dispose protection + + +- Adapts to sealed vs non-sealed automatically (private vs protected virtual) + + + + + +### How to Use + + +using (var db = new DALDB()) + + +{ + + + // use db... + + +} // Dispose() called automatically + + + + + +### Key Benefits + + +- 10+ lines of boilerplate replaced by 1 attribute + + +- sealed changes auto-adapt the Dispose pattern + + +- No manual IDisposable wiring needed + + + ::: diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md index 8f4eb76b0..a36333146 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md @@ -1,7 +1,7 @@ --- sidebar_position: 2690 title: 269 - LinkDotNet.Enumeration -description: Generating enumeration from classes in C# with matching +description: ## Summary: LinkDotNet.Enumeration slug: /LinkDotNet.Enumeration --- import Tabs from '@theme/Tabs'; @@ -49,7 +49,7 @@ Steven Giesel ## Original Readme :::note -# Enumeration +### Enumeration [![.NET](https://github.com/linkdotnet/Enumeration/actions/workflows/dotnet.yml/badge.svg)](https://github.com/linkdotnet/Enumeration/actions/workflows/dotnet.yml) [![Nuget](https://img.shields.io/nuget/dt/LinkDotNet.Enumeration)](https://www.nuget.org/packages/LinkDotNet.Enumeration/) @@ -57,7 +57,7 @@ Steven Giesel Source code generated string Enumeration with completeness! -## What is in the box? +###### What is in the box? This source code generator let's you easily create string based enumerations with a lot of features. @@ -75,7 +75,7 @@ var color = Color.Red; var color = Color.Create("Red"); ``` -## Exhaustiveness +###### Exhaustiveness The great benefit of the library is that you have support for exhaustiveness: @@ -103,9 +103,9 @@ var colorCode = color.Match( ); ``` -## More features! +###### More features! -### Controlling field names +######### Controlling field names The `Enumeration` attribute accepts an optional first argument of type `Casing` to control how the static member names are derived from the string values. By default, the library uses `PascalCase` to convert string values into member names. If you want to preserve the original casing of the string values, you can set the `Casing` to `Preserve`. @@ -127,7 +127,7 @@ public sealed partial class Color The default is `PascalCase` to feel "natural" to C# developers. -### Creating from a string key +######### Creating from a string key Two methods are exposed `Create` and `TryCreate` to create an instance of the enumeration from a string key. The `Create` method will throw an `ArgumentException` if the key is not valid, while the `TryCreate` method will return a boolean indicating whether the creation was successful and output the created value through an out parameter. @@ -144,7 +144,7 @@ else } ``` -### Parsing (IParsable) +######### Parsing (IParsable) The generated types implement `IParsable` and `ISpanParsable`, making them compatible with modern .NET features like Minimal APIs and Model Binding. @@ -155,7 +155,7 @@ if (Color.TryParse("Red", null, out var color)) } ``` -### Implicit/Explicit Conversions +######### Implicit/Explicit Conversions Instances of the generated enumeration can be implicitly converted to strings (returns the `Key` property), and strings can be explicitly converted back to the enumeration type (calls `Create`). @@ -164,7 +164,7 @@ string colorKey = Color.Red; // Implicit conversion var color = (Color)"Green"; // Explicit conversion ``` -### Equality and Comparison +######### Equality and Comparison Records implement value-based equality by default. For classes, `IEquatable` is automatically implemented, comparing the `Key` property. @@ -173,11 +173,11 @@ var isRed = Color.Red == "Red"; // String comparison var areEqual = Color.Red.Equals(Color.Create("Red")); // Value equality ``` -### Getting all values +######### Getting all values Calling `All` will return a collection of all possible values. This is implemented using a `FrozenSet` to ensure immutability and thread-safety. -## `JsonConverter` Generation +###### `JsonConverter` Generation The library allows via the `GenerateJsonConverter` property on the `Enumeration` attribute to generate a `JsonConverter` for the enumeration type. This converter will handle serialization and deserialization of the enumeration values as their string keys. @@ -188,7 +188,7 @@ public sealed partial record Color; This will generate a `JsonConverter` that can be used with `System.Text.Json` to serialize and deserialize `Color` instances as their string keys. The generated converter is called `\{TypeName}\}JsonConverter`. -### Limitations +######### Limitations * Your code should run at least `net8.0` or later, as the library uses things like `FrozenSet`. @@ -198,7 +198,64 @@ This will generate a `JsonConverter` that can be used with `System.Text.Json` to ### About :::note -Generating enumeration from classes in C# with matching +## Summary: LinkDotNet.Enumeration + + + + + +### Purpose + + +A source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns. + + + + + +### How to Define + + +[Enumeration(Casing.Preserve, "None", "Dacia", "Tesla", "BMW", "Mercedes")] + + +public sealed partial record CarTypes; + + + + + +### How to Use + + +CarTypes.TryParse("BMW", null, out var car); + + +car.Match(onBMW: () => "this is bmw", onDacia: () => "this is dacia", ...); + + + + + +### Key Features + + +- Exhaustive matching: Match() requires all values + + +- Create / TryCreate: throws vs returns bool + + +- IParsable: Minimal APIs & Model Binding + + +- Implicit string conversion + + +- CarTypes.All returns FrozenSet + + +- JSON: GenerateJsonConverter = true ::: diff --git a/v2/rscg_examples_site/static/exports/RSCG.xlsx b/v2/rscg_examples_site/static/exports/RSCG.xlsx index a1ac877bcd54526675be8b183206eda895fef1b8..c14e14b3400ca70445ede4e9c43bebf5ad10eabe 100644 GIT binary patch delta 914 zcmZ3TcO|brz?+#xgn@y9gF)MTcg$=%y^g&=o)RMi13!?i$k8v)FUn5J&(GGY$j#~P zKg)HOk2GQH!E{1#dZmnwa=6;Ec(t?zMGR5jPNIvOl>VfmSW0^;d|9*fOwLq& z6TQ!+T=!%i%JUf=GuyHF*{ci3%{>mp9o;fB+S-64a{4FssZY}L|1zL@^;CSrr+JK< z822;sfqZ^HrsbczJ_AG3kIiS9xb^FQ|43QsTs-lE(~-$WC(i`Wcg^Cy&b^RNv-en9 z`_1)-3#LTyZWE6c`?{@RfjrZZYu)D#UN1RQxhyF5%I-}zlRqdj-IcEM{vn`o@7G_S z!hhS-K5ovE3HbQ=|G)n*XE1<6Ts`-JmIg4iL6{pD;_*ePImP;Vo3)KN7|o4Lj17$~ zQ;iKwOw&w^(kzq|^zCf)gHm%6OEUBGiZe0`itS*=K_XCPclhC3le3J~>ksA~GT>>8 zSN&95%Cz*A8q@UH9ZGQuUURlB@?E6DQ?X6sX2Zk%oO5e!md(>RKlfc>;6J@bj{Y;tmad7| z>g`;5yF=b~j&0&+R#Xq))SLhC7ckr+m>3v@fpoNUeqKpxUdiSOCW4Hd@H9Pnm8l6c zkT?0EsWjuO$$w2{6i{QGi9rIW8v!;mO}@w^r5)hS$Rxr5${^UI3!%Yaa-EqJ*g{Ag gEHo2kY@EE^Oj90Y5xO%G`X*2QZ>Gk!&lDsA0PRy;mH+?% delta 825 zcmcbTw>qyrz?+#xgn@y9gCR9{R}4%3i|6}+JS9d327Vx2k)vOpUzDAcpP#K)k(<-o zf4c9G0gr3F>Zdx7^pFL?TT=}^I&^Cq)k`y7gu@FP>g*m`-o7atAAN1-)vTgst6+iC z``XS&vUTlwc!TB*T0{!CK z*VzY~{9haSXU(ixL4W@2|8Ea7m;oG$Ck&rF+U#T`&B$+=mS$;cWNKlUWR_x*Y%w{< zSY8NZ+xacqgl+@FcP}uUr5GkZG?S^{I?+1sumMlodZmK(nY*(du>@`^c`5aTX^W4& zK(vs`)6#8xwn6IywrX@qytuGb_~85}?fegZzrLMTKG&@qXDcoWCkNe`bw+nvWe0BMV+CQda0{P190_>k;-B~MS_ixtO=&;9x>s#s18&g6= zk7fm)TDH#d!G6xzHTG@uEYHoYd$i*x+ zUSOid$O%tvlP{Z^Favp$xy+<(-ayh^aY Date: Wed, 27 May 2026 07:08:52 +0300 Subject: [PATCH 5/6] buld --- .../GenerateDispose/description.json | 2 +- v2/rscg_examples/GenerateDispose/video.json | 2 +- .../LinkDotNet.Enumeration/description.json | 2 +- .../LinkDotNet.Enumeration/video.json | 2 +- .../docs/RSCG-Examples/GenerateDispose.md | 4 ++-- .../RSCG-Examples/LinkDotNet.Enumeration.md | 4 ++-- .../static/exports/RSCG.xlsx | Bin 14164 -> 14163 bytes 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/v2/rscg_examples/GenerateDispose/description.json b/v2/rscg_examples/GenerateDispose/description.json index d5e4e83a8..0b2c139ff 100644 --- a/v2/rscg_examples/GenerateDispose/description.json +++ b/v2/rscg_examples/GenerateDispose/description.json @@ -9,7 +9,7 @@ "source":"https://github.com/ItaiTzur76/GenerateDispose" }, "data":{ - "goodFor":["## Summary: GenerateDispose", + "goodFor":["GenerateDispose for boilerplate reduction for IDisposable pattern", "### Purpose", "A Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute.", "It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).", diff --git a/v2/rscg_examples/GenerateDispose/video.json b/v2/rscg_examples/GenerateDispose/video.json index a2a68d84f..8e31fe750 100644 --- a/v2/rscg_examples/GenerateDispose/video.json +++ b/v2/rscg_examples/GenerateDispose/video.json @@ -8,7 +8,7 @@ {"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 GenerateDispose . ## Summary: GenerateDispose### PurposeA Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute.It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).### How to Define[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))]partial class DALDB : IDisposable // : IDisposable is optional!{ private ConnectionDB cn; private ConnectionDB cn1; public DALDB() { cn = new ConnectionDB(); cn1 = new ConnectionDB(); } public void Drop() // Your custom disposal logic { cn.Dispose(); cn1.Dispose(); }}- The class must be partial- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments### What Gets Generated- public void Dispose() (thread-safe, calls your method)- A private int _isDisposed field for double-dispose protection- Adapts to sealed vs non-sealed automatically (private vs protected virtual)### How to Useusing (var db = new DALDB()){ // use db...} // Dispose() called automatically### Key Benefits- 10+ lines of boilerplate replaced by 1 attribute- sealed changes auto-adapt the Dispose pattern- No manual IDisposable wiring needed ."}, +{"typeStep":"text","arg": "Today I will present GenerateDispose . GenerateDispose for boilerplate reduction for IDisposable pattern### PurposeA Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute.It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).### How to Define[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))]partial class DALDB : IDisposable // : IDisposable is optional!{ private ConnectionDB cn; private ConnectionDB cn1; public DALDB() { cn = new ConnectionDB(); cn1 = new ConnectionDB(); } public void Drop() // Your custom disposal logic { cn.Dispose(); cn1.Dispose(); }}- The class must be partial- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments### What Gets Generated- public void Dispose() (thread-safe, calls your method)- A private int _isDisposed field for double-dispose protection- Adapts to sealed vs non-sealed automatically (private vs protected virtual)### How to Useusing (var db = new DALDB()){ // use db...} // Dispose() called automatically### Key Benefits- 10+ lines of boilerplate replaced by 1 attribute- sealed changes auto-adapt the Dispose pattern- No manual IDisposable wiring needed ."}, {"typeStep":"browser","arg":"https://www.nuget.org/packages/GenerateDispose/"}, {"typeStep":"text","arg": "The whole example is here"}, {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/GenerateDispose"}, diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/description.json b/v2/rscg_examples/LinkDotNet.Enumeration/description.json index 992ad7769..fbec58e79 100644 --- a/v2/rscg_examples/LinkDotNet.Enumeration/description.json +++ b/v2/rscg_examples/LinkDotNet.Enumeration/description.json @@ -9,7 +9,7 @@ "source":"https://github.com/linkdotnet/Enumeration" }, "data":{ - "goodFor":["## Summary: LinkDotNet.Enumeration", + "goodFor":["Good for replacing enum + switch patterns with string-based enumerations with exhaustive pattern matching.", "", "### Purpose", "A source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns.", diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/video.json b/v2/rscg_examples/LinkDotNet.Enumeration/video.json index c25419d34..d8f5e4c65 100644 --- a/v2/rscg_examples/LinkDotNet.Enumeration/video.json +++ b/v2/rscg_examples/LinkDotNet.Enumeration/video.json @@ -8,7 +8,7 @@ {"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 LinkDotNet.Enumeration . ## Summary: LinkDotNet.Enumeration### PurposeA source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns.### How to Define[Enumeration(Casing.Preserve, "None", "Dacia", "Tesla", "BMW", "Mercedes")]public sealed partial record CarTypes;### How to UseCarTypes.TryParse("BMW", null, out var car);car.Match(onBMW: () => "this is bmw", onDacia: () => "this is dacia", ...);### Key Features- Exhaustive matching: Match() requires all values- Create / TryCreate: throws vs returns bool- IParsable<T>: Minimal APIs & Model Binding- Implicit string conversion- CarTypes.All returns FrozenSet<CarTypes>- JSON: GenerateJsonConverter = true ."}, +{"typeStep":"text","arg": "Today I will present LinkDotNet.Enumeration . Good for replacing enum + switch patterns with string-based enumerations with exhaustive pattern matching.### PurposeA source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns.### How to Define[Enumeration(Casing.Preserve, "None", "Dacia", "Tesla", "BMW", "Mercedes")]public sealed partial record CarTypes;### How to UseCarTypes.TryParse("BMW", null, out var car);car.Match(onBMW: () => "this is bmw", onDacia: () => "this is dacia", ...);### Key Features- Exhaustive matching: Match() requires all values- Create / TryCreate: throws vs returns bool- IParsable<T>: Minimal APIs & Model Binding- Implicit string conversion- CarTypes.All returns FrozenSet<CarTypes>- JSON: GenerateJsonConverter = true ."}, {"typeStep":"browser","arg":"https://www.nuget.org/packages/LinkDotNet.Enumeration/"}, {"typeStep":"text","arg": "The whole example is here"}, {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration"}, diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md b/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md index 3c1b619a0..61cb08ca6 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md @@ -1,7 +1,7 @@ --- sidebar_position: 2680 title: 268 - GenerateDispose -description: ## Summary: GenerateDispose +description: GenerateDispose for boilerplate reduction for IDisposable pattern slug: /GenerateDispose --- import Tabs from '@theme/Tabs'; @@ -163,7 +163,7 @@ Happy coding! ### About :::note -## Summary: GenerateDispose +GenerateDispose for boilerplate reduction for IDisposable pattern ### Purpose diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md index a36333146..bc0cdea23 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md @@ -1,7 +1,7 @@ --- sidebar_position: 2690 title: 269 - LinkDotNet.Enumeration -description: ## Summary: LinkDotNet.Enumeration +description: Good for replacing enum + switch patterns with string-based enumerations with exhaustive pattern matching. slug: /LinkDotNet.Enumeration --- import Tabs from '@theme/Tabs'; @@ -198,7 +198,7 @@ This will generate a `JsonConverter` that can be used with `System.Text.Json` to ### About :::note -## Summary: LinkDotNet.Enumeration +Good for replacing enum + switch patterns with string-based enumerations with exhaustive pattern matching. diff --git a/v2/rscg_examples_site/static/exports/RSCG.xlsx b/v2/rscg_examples_site/static/exports/RSCG.xlsx index c14e14b3400ca70445ede4e9c43bebf5ad10eabe..c76735e0c2aa2c47a71db300c628f236a161018d 100644 GIT binary patch delta 645 zcmcbTcR8;p5z*RHy4kolSmq@o22?y;lP6 z_dVX(zUqoTl3;Banx(kbj8E?WJk5Gfi(JF@!-bofKl*$Ny~6k~SoopA;i+B)t0rfy zoAkt_d3*c+%tF z|MoL7@mg-)&s43?0SbY_%9#S2os6Uz1x!s%Q;btgQY;J;O-#~^(kAB`%L##$tTL|J zbrTpkdx3!@#W4AynN0oGiH?5EhCHsofH`mB>+BkMIq$}XwN;H13e()?dM>hP{g$I+ zAr!8l&|)RTZMH_I{lW#^YTae?-I7(eUrIm zXz0QA5 zJ@@$gx&^2@_-aH~WJ3 z8TWUcr|!H|Uw3MLYT?rDOSWEFvL-Ko={5h;`nGdy6Mr)z2ioTOCfbbPPy(fs$(Kw` zfk8K!)65b?xtO`Y190*LGeb^zP)$B%W)D)qZ7#z!$z<|+6Vb_b<^pVcO@U#^005>t B3i1E| delta 641 zcmcbdcO|brz?+#xgn@y9gF)MTcg$=%y^g&=o)RMi13!?i$k8v)FUn5J&(GGY$j#~P zKg)HOk2GQH!E{1#dZmnwa=6;Ec(t?zMGR5jPNIvOl>VfmSW0^;d|9*fOwLq& z6TQ!+T=!%i%JUf=GuyHF*{ci3%{>mp9o;fB+S-64a{4FssZY}L|1zL@^;CSrr+JJU z|LtdF(l+0`pQ&1(0~7-4xev59I~hqc3K*Ff8yZ`t8XK6HrkNO}Sxn9~mJ>8SN&95%Cz*A8q@UH9ZGQuUURlB@?E6DQ?X6< zn@4qPs<2bYt;Febb^dR&ubpIn-~QU|(sX2Zk% zoO5e!md(>RKlfc>;6J@bj{Y;tmad7|>g`;5yF=b~j&0&+R^(9IJkLa%5gbgQgfjV} xsVOk*CUclsf+%M*7kCIx?l&{!gooASlVrjFTs;o2#+yGX;hp0{};X0^ Date: Wed, 27 May 2026 21:24:34 +0300 Subject: [PATCH 6/6] resolved buiild errors --- v2/rscg_examples/GenerateDispose/description.json | 4 ++++ v2/rscg_examples/GenerateDispose/video.json | 2 +- .../LinkDotNet.Enumeration/description.json | 4 ++-- v2/rscg_examples/LinkDotNet.Enumeration/video.json | 2 +- .../docs/RSCG-Examples/GenerateDispose.md | 12 ++++++++++++ .../docs/RSCG-Examples/LinkDotNet.Enumeration.md | 4 ++-- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/v2/rscg_examples/GenerateDispose/description.json b/v2/rscg_examples/GenerateDispose/description.json index 0b2c139ff..2dbccef5b 100644 --- a/v2/rscg_examples/GenerateDispose/description.json +++ b/v2/rscg_examples/GenerateDispose/description.json @@ -15,6 +15,7 @@ "It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).", "", "### How to Define", +"```csharp showLineNumbers", "[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))]", "partial class DALDB : IDisposable // : IDisposable is optional!", "{", @@ -33,6 +34,7 @@ " cn1.Dispose();", " }", "}", +"```", "", "- The class must be partial", "- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments", @@ -43,11 +45,13 @@ "- Adapts to sealed vs non-sealed automatically (private vs protected virtual)", "", "### How to Use", +"```csharp showLineNumbers", "using (var db = new DALDB())", "{", " // use db...", "} // Dispose() called automatically", "", +"```", "### Key Benefits", "- 10+ lines of boilerplate replaced by 1 attribute", "- sealed changes auto-adapt the Dispose pattern", diff --git a/v2/rscg_examples/GenerateDispose/video.json b/v2/rscg_examples/GenerateDispose/video.json index 8e31fe750..ca1a3f5e0 100644 --- a/v2/rscg_examples/GenerateDispose/video.json +++ b/v2/rscg_examples/GenerateDispose/video.json @@ -8,7 +8,7 @@ {"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 GenerateDispose . GenerateDispose for boilerplate reduction for IDisposable pattern### PurposeA Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute.It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).### How to Define[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))]partial class DALDB : IDisposable // : IDisposable is optional!{ private ConnectionDB cn; private ConnectionDB cn1; public DALDB() { cn = new ConnectionDB(); cn1 = new ConnectionDB(); } public void Drop() // Your custom disposal logic { cn.Dispose(); cn1.Dispose(); }}- The class must be partial- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments### What Gets Generated- public void Dispose() (thread-safe, calls your method)- A private int _isDisposed field for double-dispose protection- Adapts to sealed vs non-sealed automatically (private vs protected virtual)### How to Useusing (var db = new DALDB()){ // use db...} // Dispose() called automatically### Key Benefits- 10+ lines of boilerplate replaced by 1 attribute- sealed changes auto-adapt the Dispose pattern- No manual IDisposable wiring needed ."}, +{"typeStep":"text","arg": "Today I will present GenerateDispose . GenerateDispose for boilerplate reduction for IDisposable pattern### PurposeA Roslyn source generator that replaces the 10+ lines of IDisposable boilerplate code with a single attribute.It also automatically adapts the generated pattern when the class modifiers change (e.g. sealed to non-sealed).### How to Define```csharp showLineNumbers[GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))]partial class DALDB : IDisposable // : IDisposable is optional!{ private ConnectionDB cn; private ConnectionDB cn1; public DALDB() { cn = new ConnectionDB(); cn1 = new ConnectionDB(); } public void Drop() // Your custom disposal logic { cn.Dispose(); cn1.Dispose(); }}```- The class must be partial- Pass nameof(YourDisposeMethod) to the attribute - the method must be callable with no arguments### What Gets Generated- public void Dispose() (thread-safe, calls your method)- A private int _isDisposed field for double-dispose protection- Adapts to sealed vs non-sealed automatically (private vs protected virtual)### How to Use```csharp showLineNumbersusing (var db = new DALDB()){ // use db...} // Dispose() called automatically```### Key Benefits- 10+ lines of boilerplate replaced by 1 attribute- sealed changes auto-adapt the Dispose pattern- No manual IDisposable wiring needed ."}, {"typeStep":"browser","arg":"https://www.nuget.org/packages/GenerateDispose/"}, {"typeStep":"text","arg": "The whole example is here"}, {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/GenerateDispose"}, diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/description.json b/v2/rscg_examples/LinkDotNet.Enumeration/description.json index fbec58e79..d83a317db 100644 --- a/v2/rscg_examples/LinkDotNet.Enumeration/description.json +++ b/v2/rscg_examples/LinkDotNet.Enumeration/description.json @@ -25,9 +25,9 @@ "### Key Features", "- Exhaustive matching: Match() requires all values", "- Create / TryCreate: throws vs returns bool", -"- IParsable: Minimal APIs & Model Binding", +"- IParsable: Minimal APIs & Model Binding", "- Implicit string conversion", -"- CarTypes.All returns FrozenSet", +"- CarTypes.All returns FrozenSet of CarTypes", "- JSON: GenerateJsonConverter = true" ], "csprojDemo":"EnumDemo.csproj", diff --git a/v2/rscg_examples/LinkDotNet.Enumeration/video.json b/v2/rscg_examples/LinkDotNet.Enumeration/video.json index d8f5e4c65..597157159 100644 --- a/v2/rscg_examples/LinkDotNet.Enumeration/video.json +++ b/v2/rscg_examples/LinkDotNet.Enumeration/video.json @@ -8,7 +8,7 @@ {"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 LinkDotNet.Enumeration . Good for replacing enum + switch patterns with string-based enumerations with exhaustive pattern matching.### PurposeA source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns.### How to Define[Enumeration(Casing.Preserve, "None", "Dacia", "Tesla", "BMW", "Mercedes")]public sealed partial record CarTypes;### How to UseCarTypes.TryParse("BMW", null, out var car);car.Match(onBMW: () => "this is bmw", onDacia: () => "this is dacia", ...);### Key Features- Exhaustive matching: Match() requires all values- Create / TryCreate: throws vs returns bool- IParsable<T>: Minimal APIs & Model Binding- Implicit string conversion- CarTypes.All returns FrozenSet<CarTypes>- JSON: GenerateJsonConverter = true ."}, +{"typeStep":"text","arg": "Today I will present LinkDotNet.Enumeration . Good for replacing enum + switch patterns with string-based enumerations with exhaustive pattern matching.### PurposeA source code generator that creates string-based enumerations (similar to Java enums / DDD value objects) with exhaustive pattern matching, replacing enum + switch patterns.### How to Define[Enumeration(Casing.Preserve, "None", "Dacia", "Tesla", "BMW", "Mercedes")]public sealed partial record CarTypes;### How to UseCarTypes.TryParse("BMW", null, out var car);car.Match(onBMW: () => "this is bmw", onDacia: () => "this is dacia", ...);### Key Features- Exhaustive matching: Match() requires all values- Create / TryCreate: throws vs returns bool- IParsable: Minimal APIs & Model Binding- Implicit string conversion- CarTypes.All returns FrozenSet of CarTypes- JSON: GenerateJsonConverter = true ."}, {"typeStep":"browser","arg":"https://www.nuget.org/packages/LinkDotNet.Enumeration/"}, {"typeStep":"text","arg": "The whole example is here"}, {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/LinkDotNet.Enumeration"}, diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md b/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md index 61cb08ca6..907a556dc 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/GenerateDispose.md @@ -181,6 +181,9 @@ It also automatically adapts the generated pattern when the class modifiers chan ### How to Define +```csharp showLineNumbers + + [GenerateDispose.SourceGenerators.GenerateDispose(nameof(Drop))] @@ -235,6 +238,9 @@ partial class DALDB : IDisposable // : IDisposable is optional! } +``` + + @@ -265,6 +271,9 @@ partial class DALDB : IDisposable // : IDisposable is optional! ### How to Use +```csharp showLineNumbers + + using (var db = new DALDB()) @@ -280,6 +289,9 @@ using (var db = new DALDB()) +``` + + ### Key Benefits diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md index bc0cdea23..56d6d6d75 100644 --- a/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md +++ b/v2/rscg_examples_site/docs/RSCG-Examples/LinkDotNet.Enumeration.md @@ -246,13 +246,13 @@ car.Match(onBMW: () => "this is bmw", onDacia: () => "this is dacia", ...); - Create / TryCreate: throws vs returns bool -- IParsable: Minimal APIs & Model Binding +- IParsable: Minimal APIs & Model Binding - Implicit string conversion -- CarTypes.All returns FrozenSet +- CarTypes.All returns FrozenSet of CarTypes - JSON: GenerateJsonConverter = true