views:

159

answers:

3

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.

A: 

Why not ToString the enum value and string.replace "_" with " ".

Or.

Maintain a lookup dictionary which is keyed against the enum value and returns the string description. You could write a nice wrapper for this, so that it would be easy to provide localization for the descriptions, for instance.

chibacity
Localization isn't needed since the value is a part of webservice description which will always be English.
Manish Sinha
Just an example. You could also make the strings configurable with a lookup\wrapper approach, so you wouldn't have to re-compile the application to change them.
chibacity
+1  A: 

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 http://geekswithblogs.net/abhijeetp/archive/2009/01/10/dynamic-attributes-in-c.aspx

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...

chibacity
Thanks! This is for accessing the attributes, but still am unable to find the way to add attributes.
Manish Sinha
I think everyone has misunderstood your question. The enum code in the question already has the attributes applied. You want to add attributes at runtime?
chibacity
Plus if you like the answer so far, a vote might be motivating... :)
chibacity
I mean that should be the final output as I asked in the question. Using reflection, the enumeration should be created, DescriptionAttribute added to each entry and I should be able to use this enum and also it's Description.
Manish Sinha
A: 

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