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

问题描述 投票:0回答:2

我有一个字符串列表,它们是枚举值的候选者。他们是

  • 不要发送差异
  • 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

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

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

DescriptionAttribute

c# .net reflection enums reflection.emit
2个回答
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 通过以下方式支持类型元数据引擎:TypeDescriptor:

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

示例<链接>

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

您也许能够改变这个机制来支持您想要做的事情,但最终您将需要维护对枚举成员的查找以提供描述字符串。使用查找结构来维护枚举成员和描述字符串之间的映射是我的第一个答案,也是这个问题的第一个答案......


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;
     }
}
© www.soinside.com 2019 - 2024. All rights reserved.