-
Notifications
You must be signed in to change notification settings - Fork 1
/
SpecializedEnum.cs
145 lines (135 loc) · 4.82 KB
/
SpecializedEnum.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// ©2008 James Coe
// http://www.codeplex.com/SpecializedEnum/
// This code is released under the Microsoft Public License. See the project page for details.
using System;
using System.Collections.Generic;
using System.Reflection;
/// <summary>
/// A generic base class for emulating some of the behaviors of an enum.
/// </summary>
/// <typeparam name="TDerived">The type (class name) of the derived class.</typeparam>
/// <typeparam name="TValues">The type of the values.</typeparam>
/// <remarks>
/// This class uses readonly variables, reflection, generics, and an internal ordered list to provide behavior similar to that of an enum.
/// Public static readonly variables can be added in the derived class to gain behavior very similar to that of an enum.
/// </remarks>
/// <example>
/// In this example we create an enumeration of names corresponding to strings.
/// <code>
/// public class FraggleTypes : SpecializedEnum<FraggleTypes, string>
/// {
/// public static readonly string mokey = "Mokey Fraggle";
/// public static readonly string red = "Red Fraggle";
/// public static readonly string wembley = "Wembley Fraggle";
/// }
/// </code>
/// </example>
public abstract class SpecializedEnum<TDerived, TValues>
where TDerived : SpecializedEnum<TDerived, TValues>
where TValues : IComparable
{
/// <summary>
/// An internal SortedList used to cache the names and values acquired by reflection.
/// </summary>
private static readonly SortedList<string, TValues> keyValuePairs = new SortedList<string, TValues>();
/// <summary>
/// Initializes the <see cref="SpecializedEnum<TMine, TValue>"/> class.
/// </summary>
/// <remarks>
/// Iterate the collection of fields on the derived class using reflection and copy the appropriate items into
/// the ordered list used as a cache. Reflection is an expensive operation, so we only want to do this
/// once. By performing the reflection caching in a static constructor and making everything static, this
/// happens only once, on the first time a member of the class is accessed and never afterwards.
/// </remarks>
static SpecializedEnum()
{
foreach (FieldInfo info in typeof(TDerived).GetFields())
{
if (info.IsStatic && info.IsPublic && info.FieldType == typeof(TValues))
{
keyValuePairs.Add(info.Name, (TValues)info.GetValue(typeof(TDerived)));
}
}
}
#region Lookup functions
/// <summary>
/// Determines whether the specified value is defined.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// <c>true</c> if the specified value is defined; otherwise, <c>false</c>.
/// </returns>
public static bool IsDefined(TValues value)
{
return keyValuePairs.ContainsValue(value);
}
/// <summary>
/// Parses the specified value from the name.
/// </summary>
/// <param name="name">Name of the value.</param>
/// <returns>The value associated with the name.</returns>
public static TValues Parse(string name)
{
if (keyValuePairs.ContainsKey(name))
{
return keyValuePairs[name];
}
else
{
return default(TValues);
}
}
/// <summary>
/// Gets the name associated with a specific value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The name associated with the value.</returns>
public static string GetName(TValues value)
{
if (keyValuePairs.ContainsValue(value))
{
return keyValuePairs.Keys[keyValuePairs.IndexOfValue(value)];
}
else
{
return null;
}
}
/// <summary>
/// Gets the assigned names.
/// </summary>
/// <returns>The assigned names in alphabetical order.</returns>
public static string[] GetNames()
{
string[] tempArray = new string[keyValuePairs.Keys.Count];
keyValuePairs.Keys.CopyTo(tempArray, 0);
return tempArray;
}
/// <summary>
/// Gets the value associated with a specific name.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>The value associated with the name.</returns>
public static TValues GetValue(string name)
{
if (keyValuePairs.ContainsKey(name))
{
return keyValuePairs[name];
}
else
{
return default(TValues);
}
}
/// <summary>
/// Gets the assigned values.
/// </summary>
/// <returns>The assigned values sorted by the alphabetical order of their names.</returns>
public static TValues[] GetValues()
{
TValues[] tempArray = new TValues[keyValuePairs.Values.Count];
keyValuePairs.Values.CopyTo(tempArray, 0);
return tempArray;
}
#endregion
}