mardi 23 août 2022

What is the best way to achieve Smart Enum design-pattern in C#?

I was using Ardalis.SmartEnum package from Nuget.org.

I actually don't find it usefull when used in the following class hierarchy:

LicenseEdition class inside LibraryA.dll

public abstract class LicenseEdition : SmartEnum<LicenseEdition, byte>
{
    public static readonly LicenseEdition Empty = new EmptyLicenseEdition();
    protected LicenseEdition(string name, byte value) : base(name, value)
    {
    }

    private class EmptyLicenseEdition : LicenseEdition
    {
        public EmptyLicenseEdition() : base("Empty", 0)
        {

        }
    }
}

MyLicenseEdition class inside LibraryB.dll

public sealed class MyLicenseEdition : LicenseEdition
{
    public static readonly MyLicenseEdition Trial = new MyLicenseEdition( nameof(Trial), 1);
    public static readonly MyLicenseEdition Full = new MyLicenseEdition(nameof(Full), 2);

    public MyLicenseEdition(string name, byte value) : base(name, value)
    {
    }
}

Now everything is good. But https://www.nuget.org/packages/Ardalis.SmartEnum package itself leaks access to List of enums that inside LibraryA.dll

If I call MyLicenseEdition.List from Console App. (It returns empty List) Why? Because Ardalis.SmartEnum doesn't collect SmartEnum classes in LibraryB that depend on base SmartEnum<LicenseEdition> class in LibraryA. So the LibraryB sub-classes of LicenseEdition should be kept with LicenseEdition in LibraryA. (I can't do that Because I must have two libraries for my reasons I may have...).

After read many posts about Smart Enums (in Term). People found Smart Enum (Term itself I don't mean Ardalis Lib) is anti-pattern way itself..

Heres one: https://dev.to/entomy/smart-enum-what-jon-skeet-got-wrong-16m4

I don't find static/const members is advanced way to achieve (Smart Enums...) Its not made for that.

Back to my Problem I need to achieve this things.

  1. I don't need to use System.Enum, Because I need inheritable enums. (LicenseEdition is base for child Smart Enums).
  2. With normal System.Enum If I need provide my abstract/custom implmenetation I should provide a Generic to my Class: i.e:

So the only way to do this trick is that:

 public enum MyEdition
    {
        Standard,
        Full
    }

 public abstract class LicenseEntity<T> where T : Enum
    {
        public abstract T LicenseEdition { get; set; }
    }

    public class MyLicenseEntity : LicenseEntity<MyEdition>
    {
        public override MyEdition LicenseEdition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

Back to Questions:

  1. What do you think about above code?
  2. What patterns you should/good for smart enums pattern (Which doesn't exist in .NET by default).
  3. Do you find it usefull? Or we should just stuck on (non-mature System.Enum pattern? (Click for reasons - Image included))

Thank you all

Aucun commentaire:

Enregistrer un commentaire