有没有到奇怪的循环模板模式的方法吗? [英] Is there an alternative to the Curiously Recurring Template Pattern?
问题描述
我自己造成了与好奇地重复模板 。模式
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?
如何改进下面的例子:
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;
}
}
这个问题,因为你会看到从我的第二个链接的问题,就是调用枚举< DocketType,整型,字符串> .Resolve(X值);
不会引起 DocketType <被实例化/ code>静态对象。
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.
我并不反对完全从头开始重写此。我知道这是一个很大的代码味道。目前,得到这个工作我的基类有受保护的静态方法 ChildResolve
和我添加解析
到每个我的枚举类。 !讨厌的东西。
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!
答:
似乎没有很好的替代模式,所以我坚持用模式,把灵感来自公认的答案以及与此想出了:
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);
}
}
这也是用在CodeCampServer MVC相同的代码示例项目,所以我觉得不太脏的使用它!
This is also the same code using in the CodeCampServer MVC example project, so I feel less dirty for using it!
推荐答案
这不是很优雅,但这样的事情可能会做的伎俩
It's not very elegant, but something like this might do the trick:
public class DocketType : Enumeration<DocketType, int, string>
{
public static readonly DocketType Withdrawal =
new DocketType(2, "Withdrawal");
public static readonly DocketType Installation =
new DocketType(3, "Installation");
private DocketType(int docketTypeId, string description)
: base(docketTypeId, description) { }
}
public abstract class Enumeration<TEnum, TId, TDescription> : IComparable
where TEnum : Enumeration<TEnum, TId, TDescription>
{
private static readonly Dictionary<TId, TEnum> _cache;
static Enumeration()
{
Type t = typeof(TEnum);
_cache = t.GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(f => f.FieldType == t)
.Select(f => (TEnum)f.GetValue(null))
.ToDictionary(e => e.Id, e => e);
}
public static TEnum Resolve(TId id)
{
return _cache[id];
}
public TId Id { get; private set; }
public TDescription Description { get; private set; }
protected Enumeration(TId id, TDescription description)
{
Id = id;
Description = description;
}
// IComparable
public int CompareTo(object obj)
{
// TODO
throw new NotImplementedException();
}
}
这篇关于有没有到奇怪的循环模板模式的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!