在过去的几周里,我用奇怪的是反复出现的模板模式给自己带来了一些头痛。
以下是我的两个问题:
如何改进以下示例:
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) { }
}我想要一个不需要在Enumeration类中重复的静态方法:
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;
}
}正如您将从我的第二个链接问题中看到的,这个问题的问题是,对Enumeration<DocketType, int, string>.Resolve(X value);的调用不会导致DocketType静态对象被实例化。
我并不反对从头开始重写这个。我知道这是一种很大的暗号气味。目前,为了使其正常工作,我的基类具有受保护的静态方法ChildResolve,并且我已经将Resolve添加到我的每个枚举类中。恶心的东西!
答案:
似乎没有一个好的替代模式,所以我坚持这个模式,并从被接受的答案中获得灵感,并得出如下结论:
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示例项目中使用的相同代码,所以我觉得使用它不那么脏!
发布于 2010-08-10 23:04:34
它不太优雅,但像这样的东西可能会起作用:
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();
}
}发布于 2010-08-10 22:02:48
您需要将您的静态字段推送到一个类中,该类的实例为instanced字段。这样,您就可以通过单个静态成员访问枚举,该成员将立即执行所有枚举成员。
一个快速拼凑起来的例子:
// The Collection of values to be enumerated
public class DocketEnum : EnumarationCollection<DocketType, int, string>
{
// Values are fields on a statically instanced version of this class
public DocketType Withdrawal = new DocketType(2, "Withdrawal");
public DocketType Installation = new DocketType(3, "Installation");
// The publicly accessible static enumeration
public static DocketEnum Values = new DocketEnum();
}
// The actual value class
public class DocketType : EnumerationValue<DocketType, int, string>
{
// Call through to the helper base constructor
public DocketType(int docketTypeId, string description)
: base(docketTypeId, description) { }
}
// Base class for the enumeration
public abstract class EnumarationCollection<TType, X, Y>
where TType : EnumerationValue<TType, X, Y>
{
// Resolve looks at the static Dictionary in the base helpers class
public TType Resolve(X value)
{
return Cache[value] as TType;
}
public static Dictionary<X, EnumerationValue<TType, X, Y> > Cache = new Dictionary<X, EnumerationValue<TType, X, Y>>();
}
// Base class for the value
public abstract class EnumerationValue<TType, X, Y>
where TType : EnumerationValue<TType, X, Y>
{
// helper constructer talks directly the the base helper class for the Enumeration
protected EnumerationValue(X value, Y displayName)
{
EnumarationCollection<TType, X,Y >.Cache.Add(value, this as TType);
}
}
class MainClass
{
public static void Main (string[] args)
{
// You can immediately resolve to the enumeration
Console.WriteLine(DocketEnum.Values.Resolve(2).ToString());
}
}发布于 2010-08-10 21:06:40
您想要“对给定类型的所有子类”做一些事情。如果不使用AppDomain.Current.GetAssemblies()并对它们进行迭代,任何这种性质的东西都是不可能的。如果采用这种方法,可以通过创建仅应用于程序集的程序集级别属性(以及应包含在子类搜索中的其他属性)来优化性能。并在准备对每个程序集调用.GetTypes()时使用该方法。
为了明确起见,下面是获取所有这些子类的示例:
Type[] subclasses = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => Attribute.IsDefined(typeof(MyEnumeartionAssemblyAttribute)))
.SelectMany(x => x.GetTypes())
.Where(x => x.BaseType != null &&
x.BaseType.IsGenericType &&
x.BaseType.GetGenericTypeDefinition() == typeof(Enumeration<,,>));从这里开始,使用每个System.Type上的反射并对静态字段做您想做的事情应该是一个简单的问题。
https://stackoverflow.com/questions/3453326
复制相似问题