作者热门文章
- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我经常需要枚举和另一个对象(本例中为字符串)之间的全局硬编码映射。我想将枚举和映射定义放在一起以阐明维护。
如您所见,在此示例中,创建了一个带有一个静态字段的令人讨厌的类。
public enum EmailTemplates
{
// Remember to edit the corresponding mapping singleton!
WelcomeEmail,
ConfirmEmail
}
public class KnownTemplates
{
public static Dictionary<EmailTemplates, string> KnownTemplates;
static KnownTemplates() {
KnownTemplates.Add(EmailTemplates.WelcomeEmail, "File1.htm");
KnownTemplates.Add(EmailTemplates.ConfirmEmail, "File2.htm");
}
}
有时映射类可以有更多的功能和一个有意义的名字,映射事件甚至可以是私有(private)的。但这只会污染维护/关联问题。
有人对此有好的模式吗?
最佳答案
可以使用属性注解枚举,然后使用反射构建字典。
[AttributeUsage(AttributeTargets.Field)]
sealed class TemplateAttribute : Attribute {
public TemplateAttribute(String fileName) {
FileName = fileName;
}
public String FileName { get; set; }
}
enum EmailTemplate {
[Template("File1.htm")]
WelcomeEmail,
[Template("File2.htm")]
ConfirmEmail
}
class KnownTemplates {
static Dictionary<EmailTemplate, String> knownTemplates;
static KnownTemplates() {
knownTemplates = typeof(EmailTemplates)
.GetFields(BindingFlags.Static | BindingFlags.Public)
.Where(fieldInfo => Attribute.IsDefined(fieldInfo, typeof(TemplateAttribute)))
.Select(
fieldInfo => new {
Value = (EmailTemplate) fieldInfo.GetValue(null),
Template = (TemplateAttribute) Attribute
.GetCustomAttribute(fieldInfo, typeof(TemplateAttribute))
}
)
.ToDictionary(x => x.Value, x => x.Template.FileName);
}
}
如果你经常这样做,你可以创建一个更通用的通用函数,它将枚举值与与该枚举值关联的属性结合起来:
static IEnumerable<Tuple<TEnum, TAttribute>> GetEnumAttributes<TEnum, TAttribute>()
where TEnum : struct
where TAttribute : Attribute {
return typeof(TEnum)
.GetFields(BindingFlags.Static | BindingFlags.Public)
.Where(fieldInfo => Attribute.IsDefined(fieldInfo, typeof(TAttribute)))
.Select(
fieldInfo => Tuple.Create(
(TEnum) fieldInfo.GetValue(null),
(TAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TAttribute))
)
);
}
然后像这样使用它:
knownTemplates = GetEnumAttributes<EmailTemplate, TemplateAttribute>()
.ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2.FileName);
为了更有趣,您可以创建一个扩展方法:
static class EmailTemplateExtensions {
static Dictionary<EmailTemplate, String> templates;
static EmailTemplateExtensions() {
templates = GetEnumAttributes<EmailTemplate, TemplateAttribute>()
.ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2.FileName);
}
public static String FileName(this EmailTemplate emailTemplate) {
String fileName;
if (templates.TryGetValue(emailTemplate, out fileName))
return fileName;
throw new ArgumentException(
String.Format("No template defined for EmailTemplate.{0}.", emailTemplate)
);
}
}
然后调用 EmailTemplate.ConfirmEmail.FileName()
将返回 File2.htm
。
关于c# - 使用枚举类保持枚举到对象的映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10307459/
我是一名优秀的程序员,十分优秀!