使用System.Reflection.Emit在枚举字段上创建DescriptionAttribute

时间:2010-05-22 15:46:06

标签: c# .net reflection enums reflection.emit

我有一个字符串列表,它们是Enumerations值的候选对象。他们是

  • 不发送差异
  • 500行
  • 1000行
  • 5000行
  • 发送整个差异

问题是空格,特殊字符不是标识符的一部分,甚至不能以数字开头,所以我将这些值清理为仅字符,数字和_

为了保留原始值,我想把这些字符串放在DescriptionAttribute中,这样最终的Enum应该看起来像

public enum DiffBehvaiour
{ 
    [Description("Don't send diffs")]
    Dont_send_diffs,
    [Description("500 lines")]
    Diff_500_lines,
    [Description("1000 lines")]
    Diff_1000_lines,
    [Description("5000 lines")]
    Diff_5000_lines,
    [Description("Send entire diff")]
    Send_entire_diff
}

然后使用代码我将检索与枚举值关联的真实字符串,以便可以将正确的字符串发送回Web服务以获取正确的资源。

我想知道如何使用System.Reflection.Emit

创建DescriptionAttribute

基本上问题是在哪里以及如何存储原始字符串,以便在选择Enumeration值时,可以检索相应的值。

我也有兴趣了解如何在需要时访问DescriptionAttribute

2 个答案:

答案 0 :(得分:2)

好的,如果你真的想使用反射:

DiffBehvaiour value = DiffBehvaiour.Dont_send_diffs;

FieldInfo enumField = value.GetType().GetField(value.ToString());

DescriptionAttribute attribute = (DescriptionAttribute)enumField.
    GetCustomAttributes(typeof(DescriptionAttribute), true)[0];

Console.WriteLine(attribute.Description);
  
    

$>不要发送差异

  

显然没有错误处理等,但基本的想法就在那里。

<强>更新

我现在认为我看到了你的问题,我自己和其他回答的人实际上错过了。

您希望在运行时使用属性修饰枚举,即在运行时向属性添加属性。在运行时向类型添加属性可能。

然而,通过以下方式支持.Net中的类型元数据引擎: TypeDescritor

MSDN http://msdn.microsoft.com/en-us/library/system.componentmodel.typedescriptor.aspx

示例http://geekswithblogs.net/abhijeetp/archive/2009/01/10/dynamic-attributes-in-c.aspx

TypeDescritor框架允许您动态提供类型信息,而不是直接动态地装饰类型 - 它是一个间接层。

您可以弯曲此机制以支持您想要执行的操作,但在一天结束时,您需要维护枚举成员的查找以提供描述字符串。使用查找结构来维护你的枚举成员和描述字符串之间的映射是我的第一个答案,也是这个问题的第一个答案......

答案 1 :(得分:0)

您可以编写如下通用方法:

class EnumExtensions
{
     public static string GetDescription<TEnum>(TEnum value)
         // inexpressible generic constraint TEnum : System.Enum
     {
         // reflection lookup of this value per @chibacity answer
     }

     public static IDictionary<TEnum,string> GetDescriptions<TEnum>()
         // inexpressible generic constraint TEnum : System.Enum
     {
         // do the reflection lookups once and build a dictionary
         var result = new Dictionary<TEnum, string>();

         foreach(string name in Enum.GetNames(typeof(TEnum))
         {
             var value = (TEnum)Enum.Parse(typeof(TEnum), name);
             var description = GetDescription(value);

             result.Add(value, description);
         }

         return result;
     }
}