有没有到奇怪的循环模板模式的方法吗? [英] Is there an alternative to the Curiously Recurring Template Pattern?

查看:119
本文介绍了有没有到奇怪的循环模板模式的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我自己造成了与好奇地重复模板 。模式

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:

如何改进下面的例子:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆