3
3
using System ;
4
4
using Newtonsoft . Json ;
5
5
using Enum . Ext . Converter ;
6
+ using System . Reflection ;
6
7
7
8
namespace Enum . Ext
8
9
{
9
10
[ JsonConverter ( typeof ( JsonTypeSafeEnumConverter ) ) ]
10
- public abstract class TypeSafeEnum < TValue , TKey > where TKey : struct
11
+ public abstract class TypeSafeEnum < TValue , TKey > : IEquatable < TypeSafeEnum < TValue , TKey > > , IComparable < TypeSafeEnum < TValue , TKey > >
12
+ where TKey : struct , IEquatable < TKey > , IComparable < TKey >
13
+ where TValue : TypeSafeEnum < TValue , TKey >
11
14
{
12
- protected static readonly Dictionary < TKey , TypeSafeEnum < TValue , TKey > > Dictionary = new Dictionary < TKey , TypeSafeEnum < TValue , TKey > > ( ) ;
15
+ protected static readonly Lazy < Dictionary < TKey , TValue > > Dictionary = new Lazy < Dictionary < TKey , TValue > > ( ( ) => GetAllOptions ( ) . ToDictionary ( e => e . Id ) ) ;
13
16
14
- private static IEnumerable < TValue > _list ;
17
+ private static IReadOnlyCollection < TValue > _list ;
15
18
16
19
protected TypeSafeEnum ( TKey id )
17
20
{
18
- if ( Dictionary . ContainsKey ( id ) )
19
- {
20
- throw new ArgumentException ( "element with same id cannot be initialized multiple times" , nameof ( id ) ) ;
21
- }
22
-
23
21
Id = id ;
24
- Dictionary [ id ] = this ;
25
22
}
26
23
27
24
public TKey Id { get ; private set ; }
28
25
29
26
/// <summary>
30
27
/// Holds all declared values of the specific enum.
31
28
/// </summary>
32
- public static IEnumerable < TValue > List => _list ?? ( _list = Dictionary . Values . Cast < TValue > ( ) ) ;
29
+ public static IReadOnlyCollection < TValue > List => _list ?? ( _list = Dictionary . Value . Values . Cast < TValue > ( ) . ToList ( ) ) ;
33
30
34
31
public static TypeSafeEnum < TValue , TKey > GetById ( TKey value )
35
32
{
36
- return Dictionary [ value ] ;
33
+ return Dictionary . Value [ value ] ;
34
+ }
35
+
36
+ #region overrides
37
+
38
+ public override int GetHashCode ( )
39
+ {
40
+ return Id . GetHashCode ( ) ;
41
+ }
42
+
43
+ public override bool Equals ( object obj )
44
+ {
45
+ return obj is TypeSafeEnum < TValue , TKey > other && Equals ( other ) ;
46
+ }
47
+
48
+ public bool Equals ( TypeSafeEnum < TValue , TKey > other )
49
+ {
50
+ if ( object . ReferenceEquals ( this , other ) )
51
+ return true ;
52
+
53
+ if ( other is null )
54
+ return false ;
55
+
56
+ return Id . Equals ( other . Id ) ;
57
+ }
58
+
59
+ public int CompareTo ( TypeSafeEnum < TValue , TKey > other )
60
+ {
61
+ return Id . CompareTo ( other . Id ) ;
62
+ }
63
+
64
+ public static bool operator == ( TypeSafeEnum < TValue , TKey > left , TypeSafeEnum < TValue , TKey > right )
65
+ {
66
+ if ( left is null )
67
+ return right is null ;
68
+
69
+ return left . Equals ( right ) ;
70
+ }
71
+
72
+ public static bool operator != ( TypeSafeEnum < TValue , TKey > left , TypeSafeEnum < TValue , TKey > right )
73
+ {
74
+ return ! ( left == right ) ;
37
75
}
38
76
39
77
public static implicit operator TKey ( TypeSafeEnum < TValue , TKey > value )
@@ -43,7 +81,28 @@ public static implicit operator TKey(TypeSafeEnum<TValue, TKey> value)
43
81
44
82
public static implicit operator TypeSafeEnum < TValue , TKey > ( TKey value )
45
83
{
46
- return Dictionary [ value ] ;
84
+ return Dictionary . Value [ value ] ;
47
85
}
86
+
87
+ #endregion overrides
88
+
89
+ #region static methods
90
+
91
+ private static IEnumerable < TValue > GetAllOptions ( )
92
+ {
93
+ Type baseType = typeof ( TValue ) ;
94
+ IEnumerable < Type > enumTypes = Assembly . GetAssembly ( baseType ) . GetTypes ( ) . Where ( t => baseType . IsAssignableFrom ( t ) ) ;
95
+
96
+ List < TValue > options = new List < TValue > ( ) ;
97
+ foreach ( Type enumType in enumTypes )
98
+ {
99
+ List < TValue > typeEnumOptions = enumType . GetFieldsOfType < TValue > ( ) ;
100
+ options . AddRange ( typeEnumOptions ) ;
101
+ }
102
+
103
+ return options . ToList ( ) ;
104
+ }
105
+
106
+ #endregion static methods
48
107
}
49
108
}
0 commit comments