lucamilan
1/19/2016 - 9:07 PM

Strong enumerations.

Strong enumerations.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Clado.Models
{
    public interface IEnumeration<TKey> where TKey : IComparable
    {
        string Name { get; }
        TKey Value { get; }
    }

    public abstract class Enumeration<TKey> : IEnumeration<TKey>, IEquatable<Enumeration<TKey>>, IComparable<Enumeration<TKey>> where TKey : IComparable
    {
        protected Enumeration(TKey value, string name)
        {
            Value = value;
            Name = name;
        }

        public string Name { get; private set; }
        public TKey Value { get; private set; }

        public static bool operator !=(Enumeration<TKey> left, Enumeration<TKey> right)
        {
            return !Equals(left, right);
        }

        public static bool operator ==(Enumeration<TKey> left, Enumeration<TKey> right)
        {
            return Equals(left, right);
        }

        public int CompareTo(Enumeration<TKey> other)
        {
            if (ReferenceEquals(this, other))
            {
                return 0;
            }
            if (other == null)
            {
                return 1;
            }

            return other.Value.CompareTo(Value);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != GetType())
            {
                return false;
            }
            return Equals((Enumeration<TKey>)obj);
        }

        public bool Equals(Enumeration<TKey> other)
        {
            if (other == null)
            {
                return false;
            }

            return Value.Equals(other.Value);
        }

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

    public abstract class Enumeration<TEnumeration, TKey> : Enumeration<TKey> where TEnumeration : IEnumeration<TKey> where TKey : IComparable
    {
        static readonly FieldInfo[] fields = typeof(TEnumeration).GetFields(BindingFlags.Public | BindingFlags.Static);

        protected Enumeration(TKey value, string name) : base(value, name)
        {
        }

        public static TEnumeration[] All()
        {
            return fields.Select(_ => _.GetValue(null))
                         .Where(_ => _ is TEnumeration)
                         .Cast<TEnumeration>()
                         .ToArray();
        }
        
        public static IDictionary<TKey, string> ToDictionary()
        {
            return All().ToDictionary(_=>_.Value,_=>_.Name);
        }

        public static TEnumeration Get(TKey value)
        {
            return All().Where(_ => _.Value.Equals(value)).Single();
        }

        public static TEnumeration Find(TKey value)
        {
            return All().Where(_ => _.Value.Equals(value)).SingleOrDefault();
        }
    }
}