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

发布于 2024-09-02 17:37:00 字数 843 浏览 2 评论 0原文

我有一个作为枚举值候选的字符串列表。它们是

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

I have a list of strings which are candidates for Enumerations values. They are

  • Don't send diffs
  • 500 lines
  • 1000 lines
  • 5000 lines
  • Send entire diff

The problem is that spaces, special characters are not a part of identifiers and even cannot start with a number, so I would be sanitizing these values to only chars, numbers and _

To keep the original values I thought of putting these strings in the DescriptionAttribute, such that the final Enum should look like

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
}

Then later using code I will retrieve the real string associated with the enumeration value, so that the correct string can be sent back the web service to get the correct resource.

I want to know how to create the DescriptionAttribute using System.Reflection.Emit

Basically the question is where and how to store the original string so that when the Enumeration value is chosen, the corresponding value can be retrieved.

I am also interested in knowing how to access DescriptionAttribute when needed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

垂暮老矣 2024-09-09 17:37:00

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

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 框架允许您动态提供类型信息,而不是直接实际动态装饰类型 - 它是一个间接层。

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

Ok, if you really want to use reflection:

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

$> Don't send diffs

Obviously there is no error handling, etc, but the basic idea is there.

Update

I now think I see the point of your question, which myself and the other people that answered actually missed.

You want to decorate an enum with attributes at runtime i.e. add attributes to a type at runtime. Adding attributes to a type at runtime is not possible.

However these is support in the .Net for a type metadata engine via : TypeDescritor:

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

Example <Link>

The TypeDescritor framework allows you to dynamically provide type information rather than actually dynamically decorating types directly - it is a layer of indirection.

You may be able to bend this mechanism to support what you want to do, but at the end of the day you will need to maintain a lookup for your enum members to provide the description strings. Using a lookup structure to maintain a mapping between your enum members and description string was my first answer and the first answer to this question...

貪欢 2024-09-09 17:37:00

您可以编写这样的通用方法:

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

You could write a generic method like this:

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;
     }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文