使用枚举类保持枚举对象映射? [英] Keep enum-to-object mapping with enum class?

查看:108
本文介绍了使用枚举类保持枚举对象映射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常需要枚举和另一个对象之间的全局硬编码映射(本示例中是一个字符串)。我想共同定位枚举和映射定义来澄清维护。



正如你所看到的,在这个例子中,创建了一个有一个静态字段的烦人的类。 / p>

  public enum EmailTemplates 
{
//记住编辑相应的映射单例!
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);
}
}

有时,映射类可以有更多的功能和有意义的名称,映射活动甚至可以是私有的。但是这只会污染维护/相关问题。



任何人都有一个很好的模式?

解决方案

您可以使用属性来注释枚举,然后使用反射来构建字典。

  AttributeUsage(AttributeTargets.Field)] 
密封类TemplateAttribute:属性{

public TemplateAttribute(String fileName){
FileName = fileName;
}

public String FileName {get;组;

}

枚举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 =>属性.IsDefined(fieldInfo,typeof(TemplateAttribute)))
.Select(
fieldInfo => new {
Value =(EmailTemplate)fieldInfo.GetValue(null),
Template = (TemplateAttribute)属性
.GetCustomAttribute(fieldInfo,typeof(TemplateAttribute))
}

.ToDictionary(x => x.Value,x => x.Template 。文件名);
}

}

如果你这么做可以创建一个更通用的通用函数,将枚举值与与该枚举值相关联的属性组合起来:

  static IEnumerable< Tuple< TEnum ,TAttribute>>> GetEnumAttributes< TEnum,TAttribute>()
其中TEnum:struct
其中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>模板;

static EmailTemplateExtensions(){
templates = GetEnumAttributes< EmailTemplate,TemplateAttribute>()
.ToDictionary(tuple => tuple.Item1,tuple => tuple.Item2。文件名);
}

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


I frequently need a global hard-coded mapping between an enum and another object (a string in this example). I want to co-locate the enum and mapping definitions to clarify maintenance.

As you can see, in this example, an annoying class with one static field is created.

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");
    }
}

Sometimes the mapping class can have more function and a meaningful name, and the mapping activity can even be private. But that only pollutes the maintenance/correlation problem.

Anyone have a good pattern for this?

解决方案

You can use attributes to annotate the enumeration and then use reflection to build the dictionary.

[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);
  }

}

If you do this a lot you can create a more general generic function that combines enumeration values with an attribute associated with that enumeration value:

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))
      )
    );
}

And use it like this:

knownTemplates = GetEnumAttributes<EmailTemplate, TemplateAttribute>()
  .ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2.FileName);

For even more fun you can create an extension method:

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)
    );
  }

}

Then calling EmailTemplate.ConfirmEmail.FileName() will return File2.htm.

这篇关于使用枚举类保持枚举对象映射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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