mikaelsnavy
12/15/2017 - 2:40 PM

Enum Classes

//https://ardalis.com/listing-strongly-typed-enum-options-in-c
public class JobTitle
{
    // this must appear before other static instance types.
    public static List<JobTitle> AllTitles { get; } = new List<JobTitle>();
 
    public static JobTitle Author { get; } = new JobTitle(0, "Author");
    public static JobTitle Editor { get; } = new JobTitle(1, "Editor");
    public static JobTitle Administrator { get; } = new JobTitle(2, "Administrator");
    public static JobTitle SalesRep { get; } = new JobTitle(3, "Sales Representative");
 
    public string Name { get; private set; }
    public int Value { get; private set; }
 
    private JobTitle(int val, string name)
    {
        Value = val;
        Name = name;
        AllTitles.Add(this);
    }
    
    public static Role FromString(string roleString)
    {
        return List().FirstOrDefault(r => String.Equals(r.Name, roleString, StringComparison.OrdinalIgnoreCase));
    }
 
    public static Role FromValue(int value)
    {
        return List().FirstOrDefault(r => r.Value == value);
    }
}
public abstract class Enumeration : IComparable
{
    private readonly int _value;
    private readonly string _displayName;

    protected Enumeration()
    {
    }

    protected Enumeration(int value, string displayName)
    {
        _value = value;
        _displayName = displayName;
    }

    public int Value
    {
        get { return _value; }
    }

    public string DisplayName
    {
        get { return _displayName; }
    }

    public override string ToString()
    {
        return DisplayName;
    }

    public static IEnumerable<T> GetAll<T>() where T : Enumeration, new()
    {
        var type = typeof(T);
        var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);

        foreach (var info in fields)
        {
            var instance = new T();
            var locatedValue = info.GetValue(instance) as T;

            if (locatedValue != null)
            {
                yield return locatedValue;
            }
        }
    }

    public override bool Equals(object obj)
    {
        var otherValue = obj as Enumeration;

        if (otherValue == null)
        {
            return false;
        }

        var typeMatches = GetType().Equals(obj.GetType());
        var valueMatches = _value.Equals(otherValue.Value);

        return typeMatches && valueMatches;
    }

    public override int GetHashCode()
    {
        return _value.GetHashCode();
    }

    public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)
    {
        var absoluteDifference = Math.Abs(firstValue.Value - secondValue.Value);
        return absoluteDifference;
    }

    public static T FromValue<T>(int value) where T : Enumeration, new()
    {
        var matchingItem = parse<T, int>(value, "value", item => item.Value == value);
        return matchingItem;
    }

    public static T FromDisplayName<T>(string displayName) where T : Enumeration, new()
    {
        var matchingItem = parse<T, string>(displayName, "display name", item => item.DisplayName == displayName);
        return matchingItem;
    }

    private static T parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration, new()
    {
        var matchingItem = GetAll<T>().FirstOrDefault(predicate);

        if (matchingItem == null)
        {
            var message = string.Format("'{0}' is not a valid {1} in {2}", value, description, typeof(T));
            throw new ApplicationException(message);
        }

        return matchingItem;
    }

    public int CompareTo(object other)
    {
        return Value.CompareTo(((Enumeration)other).Value);
    }
}