I've caused myself some headaches over the past couple of weeks with the curiously recurring template pattern.
Following on from these two questions of mine:
- What’s the correct way of retrieving my custom enumeration classes by their value?
- Why are my static objects not being instantiated when first access to the static class is a static method on the base class?
How can I improve the following example:
public class DocketType : Enumeration<DocketType, int, string>
{
public static DocketType Withdrawal = new DocketType(2, "Withdrawal");
public static DocketType Installation = new DocketType(3, "Installation");
private DocketType(int docketTypeId, string description)
: base(docketTypeId, description) { }
}
I want a static method that I don't have to repeat in the Enumeration
class:
public abstract class Enumeration<TEnum, X, Y> : IComparable
where TEnum : Enumeration<TEnum, X, Y>
{
protected Enumeration(X value, Y displayName)
{
AddToStaticCache(this);
}
public static TEnum Resolve(X value)
{
return Cache[value] as TEnum;
}
}
The problem with this, as you'll see from my second linked question, is that the call to Enumeration<DocketType, int, string>.Resolve(X value);
does not cause the DocketType
static objects to be instantiated.
I'm not adverse to totally rewriting this from scratch. I'm aware it's a big code smell. Currently, to get this working my base class has the protected static method ChildResolve
and I've added Resolve
to each of my Enumeration classes. Nasty stuff!
ANSWER:
Seems there was no nice alternative to the pattern, so I stuck with the pattern and took inspiration from the accepted answer and came up with this:
static Enumeration()
{
GetAll();
}
public static void GetAll()
{
var type = typeof(TEnum);
var fields = type.GetFields(BindingFlags.Public |
BindingFlags.Static | BindingFlags.DeclaredOnly);
foreach (var info in fields)
{
var locatedValue = info.GetValue(null) as Enumeration<TEnum, X, Y>;
Cache.Add(locatedValue.Value, locatedValue);
}
}
This is also the same code using in the CodeCampServer MVC example project, so I feel less dirty for using it!