{"id":13629486,"url":"https://github.com/joseftw/jos.enumeration","last_synced_at":"2026-01-14T05:02:49.463Z","repository":{"id":151700212,"uuid":"537829535","full_name":"joseftw/jos.enumeration","owner":"joseftw","description":null,"archived":false,"fork":false,"pushed_at":"2025-11-21T06:52:33.000Z","size":247,"stargazers_count":33,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-27T12:36:31.752Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joseftw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-09-17T14:15:03.000Z","updated_at":"2025-11-21T06:52:30.000Z","dependencies_parsed_at":null,"dependency_job_id":"31c3dd78-6866-4fb4-9cb3-da0040776ad6","html_url":"https://github.com/joseftw/jos.enumeration","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/joseftw/jos.enumeration","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseftw%2Fjos.enumeration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseftw%2Fjos.enumeration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseftw%2Fjos.enumeration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseftw%2Fjos.enumeration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joseftw","download_url":"https://codeload.github.com/joseftw/jos.enumeration/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseftw%2Fjos.enumeration/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28410125,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T22:01:11.814Z","updated_at":"2026-01-14T05:02:49.457Z","avatar_url":"https://github.com/joseftw.png","language":"C#","funding_links":[],"categories":["Source Generators","Content"],"sub_categories":["Enums","202. [jos.enumeration](https://ignatandrei.github.io/RSCG_Examples/v2/docs/jos.enumeration) , in the [Enum](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enum) category"],"readme":"# JOS.Enumeration\nEnumeration implementation with source generation support.\n\n## Installation\n### JOS.Enumeration\nContains the `IEnumeration interface` and a `System.Text.Json` JsonConverter.\nThe `JOS.Enumeration.SourceGenerator` package contains the actual source generator.\n\n**Don't forget to install that one as well.** 😃\n\n```\ndotnet add package JOS.Enumeration\ndotnet add package JOS.Enumeration.SourceGenerator\n```\n\n### JOS.Enumeration.Database.Dapper\nContains a custom `TypeHandler` to use with Dapper.\n\n`dotnet add package JOS.Enumeration.Database.Dapper`\n\n### JOS.Enumeration.Database.EntityFrameworkCore\nContains ConfigureEnumeration extension method to allow usage with EntityFramework Core.\n\n`dotnet add package JOS.Enumeration.Database.EntityFrameworkCore`\n\n## Usage\n* Create a new *partial* `record` or `class`\n* Implement the `IEnumeration\u003cT\u003e` interface\n* Add your Enumeration items\n```csharp\npublic partial record Hamburger : IEnumeration\u003cHamburger\u003e\n{\n    public static readonly Hamburger Cheeseburger = new (1, \"Cheeseburger\");\n    public static readonly Hamburger BigMac = new(2, \"Big Mac\");\n    public static readonly Hamburger BigTasty = new(3, \"Big Tasty\");\n}\n```\nThe source generator will implement the following interface:\n```csharp\n// Default implementation -\u003e int as Value\npublic interface IEnumeration\u003cT\u003e : IEnumeration\u003cint, T\u003e where T : IEnumeration\u003cT\u003e\n{\n}\n\npublic interface IEnumeration\u003cTValue, TType\u003e where TValue : IConvertible\n{\n    TValue Value { get; }\n    string Description { get; }\n    static abstract IReadOnlySet\u003cTType\u003e GetAll();\n    static abstract IEnumerable\u003cTType\u003e GetEnumerable();\n    static abstract TType FromValue(TValue value);\n    static abstract TType FromDescription(string description);\n    static abstract TType FromDescription(ReadOnlySpan\u003cchar\u003e description);\n    static abstract Type ValueType { get; }\n}\n```\nThe following code will be generated:\n```csharp\n[System.Diagnostics.DebuggerDisplay(\"{Description}\")]\n[System.CodeDom.Compiler.GeneratedCode(\"JOS.Enumeration.SourceGenerator\", \"4.1.11-beta+afeaa87a52\")]\n[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]\npublic partial record Hamburger : IComparable\u003cJOS.Enumerations.Hamburger\u003e\n{\n    private static readonly IReadOnlySet\u003cJOS.Enumerations.Hamburger\u003e AllItems;\n    static Hamburger()\n    {\n        AllItems = new HashSet\u003cJOS.Enumerations.Hamburger\u003e(3)\n        {\n            Cheeseburger,\n            BigMac,\n            BigTasty,\n        }.ToFrozenSet();\n    }\n\n    private Hamburger(int value, string description)\n    {\n        Value = value;\n        Description = description ?? throw new ArgumentNullException(nameof(description));\n    }\n\n    public int Value { get; }\n    public string Description { get; }\n\n    public static IReadOnlySet\u003cJOS.Enumerations.Hamburger\u003e GetAll()\n    {\n        return AllItems;\n    }\n\n    public static IEnumerable\u003cJOS.Enumerations.Hamburger\u003e GetEnumerable()\n    {\n        yield return Cheeseburger;\n        yield return BigMac;\n        yield return BigTasty;\n    }\n\n    public static JOS.Enumerations.Hamburger FromValue(int value)\n    {\n        return value switch\n        {\n            1 =\u003e Cheeseburger,\n            2 =\u003e BigMac,\n            3 =\u003e BigTasty,\n            _ =\u003e throw new InvalidOperationException($\"'{value}' is not a valid value in 'JOS.Enumerations.Hamburger'\")};\n    }\n\n    public static JOS.Enumerations.Hamburger FromDescription(string description)\n    {\n        return description switch\n        {\n            \"Cheeseburger\" =\u003e Cheeseburger,\n            \"Big Mac\" =\u003e BigMac,\n            \"Big Tasty\" =\u003e BigTasty,\n            _ =\u003e throw new InvalidOperationException($\"'{description}' is not a valid description in 'JOS.Enumerations.Hamburger'\")};\n    }\n\n    public static JOS.Enumerations.Hamburger FromDescription(ReadOnlySpan\u003cchar\u003e description)\n    {\n        return description switch\n        {\n            \"Cheeseburger\" =\u003e Cheeseburger,\n            \"Big Mac\" =\u003e BigMac,\n            \"Big Tasty\" =\u003e BigTasty,\n            _ =\u003e throw new InvalidOperationException($\"'{description}' is not a valid description in 'JOS.Enumerations.Hamburger'\")};\n    }\n\n    public static Type ValueType =\u003e typeof(int);\n\n    public int CompareTo(JOS.Enumerations.Hamburger? other) =\u003e Value.CompareTo(other!.Value);\n    public static implicit operator int (JOS.Enumerations.Hamburger item) =\u003e item.Value;\n    public static implicit operator JOS.Enumerations.Hamburger(int value) =\u003e FromValue(value);\n}\n```\n## Features\n* Generic value\n* Generated `IComparable\u003cT\u003e` method.\n* Generated implicit operators (convert to/from int).\n* Generated optimized `GetAll`, `FromValue` and `FromDescription` methods.\n* System.Text.Json support\n* Database support (Dapper and EF Core).\n\n### Generic value\n\nIt's possible to use a generic value instead of the default `int` value by implementing the `IEnumeration\u003cTValue, TEnumeration\u003e` interface.\n\n```csharp\npublic partial record Car : IEnumeration\u003cstring, Car\u003e\n{\n    public static readonly Car FerrariSpider = new(\"ferrari-spider\", \"Ferrari Spider\");\n    public static readonly Car TeslaModelY = new(\"tesla-model-y\", \"Tesla Model Y\");\n}\n```\n`TValue` has a [*IConvertible*](https://learn.microsoft.com/en-us/dotnet/api/system.iconvertible?WT.mc_id=DT-MVP-5004074) constraint.\n\nThe following types has been tested and are guaranteed to work:\n* int (default)\n* bool\n* decimal\n* long\n* string\n* uint\n* ulong\n\n### JSON\nThe package comes with a `JsonConverterFactory`.\nExample:\n```csharp\nvar jsonSerializerOptions = new JsonSerializerOptions\n{\n    Converters = { new EnumerationJsonConverterFactory() }\n};\n```\n\nIt supports the following scenarios:\n* Serializing to `TValue`\n* Deserializing from `TValue`\n\nIf you want any other behaviour, just create your own converter and register it.\n\n### Database\n```csharp\npublic class MyEntity\n{\n    public MyEntity(Guid id, Hamburger hamburger)\n    {\n        Id = id;\n        Hamburger = hamburger;\n    }\n\n    public Guid Id { get; }\n    public Hamburger Hamburger { get; }\n}\n```\n#### Dapper\n* Register the TypeHandler: `SqlMapper.AddTypeHandler(new EnumerationTypeHandler\u003cHamburger\u003e())`\n* Query like this:\n```csharp\nvar results = (await actConnection.QueryAsync\u003cMyEntity\u003e(\n            \"SELECT id, hamburger from my_entities WHERE id = @id\", new {id = myEntity.Id})).ToList(); \n```\n\n#### EF Core\n* Configure your DB Context\n```csharp\npublic DbSet\u003cMyEntity\u003e MyEntities { get; set; } = null!;\n\nprotected override void OnModelCreating(ModelBuilder modelBuilder)\n{\n    modelBuilder.ApplyConfigurationsFromAssembly(typeof(JosEnumerationDbContext).Assembly);\n} \n```\n```csharp\npublic class MyEntityEntityTypeConfiguration : IEntityTypeConfiguration\u003cMyEntity\u003e\n{\n    public void Configure(EntityTypeBuilder\u003cMyEntity\u003e builder)\n    {\n        builder.HasKey(x =\u003e x.Id);\n        builder.Property(x =\u003e x.Hamburger).ConfigureEnumeration().IsRequired();\n    }\n}\n```\n* Query:\n```csharp\nvar result = await myDbContext.MyEntities.FirstAsync(x =\u003e x.Id == myEntity.Id); \n```\n### Primitive Collections\nSupport for primitive collections in net8.0 can be configured like this:\n\n#### EF Core\n```csharp\npublic void Configure(EntityTypeBuilder\u003cMyEntity\u003e builder)\n{\n    builder.ConfigureEnumeration\u003cMyEntity, string, Car\u003e(x =\u003e x.Cars);\n}\n```\n\n#### Dapper\n```csharp\nSqlMapper.AddTypeHandler(new EnumerationArrayTypeHandler\u003cstring, Car\u003e());\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoseftw%2Fjos.enumeration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoseftw%2Fjos.enumeration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoseftw%2Fjos.enumeration/lists"}