| Microsoft | Articles | Forums | FAQs |
| C# .NET |  |  |  |  |
| VB.NET |  |  |  |  |
| Visual Studio .NET |  |  |  |  |
| ADO.NET |  |  |  |  |
| Xml / Xslt |  |  |  |  |
| VB 6.0 |  |  |  |  |
| .NET CF |  |  |  |  |
| GDI+ |  |  |  |  |
| LINQ |  |  |  |  |
| Deployment |  |  |  |  |
| Security |  |  |  |  |
| FoxPro |  |  |  |  |
| Silverlight / WPF |  |  |  |  |
| Entity Framework |  |  |  |  |
| RIA Services |  |  |  |  |
|
| Web | Articles | Forums | FAQs |
| JavaScript |  |  |  |  |
| ASP |  |  |  |  |
| ASP.NET |  |  |  |  |
| WCF |  |  |  |  |
|
| Databases | Articles | Forums | FAQs |
| SQL Server |  |  |  |  |
| Access |  |  |  |  |
| Oracle |  |  |  |  |
| MySQL |  |  |  |  |
| Other Databases |  |  |  |  |
|
| Office | Articles | Forums | FAQs |
| Excel |  |  |  |  |
| Word |  |  |  |  |
| Powerpoint |  |  |  |  |
| Outlook |  |  |  |  |
| Publisher |  |  |  |  |
| Money |  |  |  |  |
|
| Non-Microsoft | Articles | Forums | FAQs |
| NHibernate |  |  |  |  |
| Perl |  |  |  |  |
| PHP |  |  |  |  |
| Ruby |  |  |  |  |
| Java |  |  |  |  |
| Linux / Unix |  |  |  |  |
| Apple |  |  |  |  |
| Open Source |  |  |  |  |
|
| Operating Sys | Articles | Forums | FAQs |
| Windows 7 |  |  |  |  |
| Windows Server |  |  |  |  |
| Windows Vista |  |  |  |  |
| Windows XP |  |  |  |  |
| Windows Update |  |  |  |  |
| MAC |  |  |  |  |
| Linux / UNIX |  |  |  |  |
|
| Server Platforms | Articles | Forums | FAQs |
 |  |  |  |  |
| BizTalk |  |  |  |  |
| Site Server |  |  |  |  |
| Exhange Server |  |  |  |  |
| IIS |  |  |  |  |
|
| Graphic Design | Articles | Forums | FAQs |
| Macromedia Flash |  |  |  |  |
| Adobe PhotoShop |  |  |  |  |
| Expression Blend |  |  |  |  |
| Expression Design |  |  |  |  |
| Expression Web |  |  |  |  |
|
| Other | Articles | Forums | FAQs |
| Lounge |  |  |  |  |
| Subversion / CVS |  |  |  |  |
| Ask Dr. Dotnetsky |  |  |  |  |
| Active Directory |  |  |  |  |
| Networking |  |  |  |  |
| Uninstall Virus |  |  |  |  |
| Job Openings |  |  |  |  |
| Product Reviews |  |  |  |  |
| Search Engines |  |  |  |  |
| Resumes |  |  |  |  |
|
| |
|
|
|
Using Attributes with Enums By Peter Bromberg Printer Friendly Version View My Articles 536 Views |  |
Attributes are a mechanism for adding metadata. Reflection is the process by which a program can read its own metadata. This article shows how to add attributes to an enum, and how to read out the attributes via Reflection. |
An attribute is an object that represents the data that is associated with a program element. The element to which an attribute is attached is called the target of that attribute.
Attribute targets can be one of the following: All, Assembly, Class, Constructor, Delegate, Enum, Event, Field, Interface, Method, Module, Parameter, Property, ReturnValue, and Struct. This gives us a lot of flexibility in how we can use attributes. This example will show how to add attributes to an enum, a technique that can be very useful in a range of paradigms.
The easiest way to illustrate the concept is to look at a "short but complete" example program:
using System;
using System.Reflection;
public enum Animals
{
[AnimalWeight(1304)]
[AnimalColor("Brown")]
DONKEY = 1,
[AnimalWeight(3250)]
[AnimalColor("Grey")]
ELEPHANT = 2
}
class AnimalWeightAttribute : Attribute
{
private readonly int weight;
public AnimalWeightAttribute(int weight) { this.weight = weight; }
public override string ToString()
{
return "weight = " +
weight.ToString();
}
}
class AnimalColorAttribute : Attribute
{
private readonly string color;
public AnimalColorAttribute(string color) { this.color = color; }
public override string ToString()
{ return "Color = " +
color.ToString();
}
}
static class Program
{
static void Main()
{
Type dataType = Enum.GetUnderlyingType(typeof(Animals));
foreach (FieldInfo field in
typeof(Animals).GetFields(BindingFlags.Static | BindingFlags.GetField |
BindingFlags.Public))
{
object value = field.GetValue(null);
Console.WriteLine("{0}={1}", field.Name,
Convert.ChangeType(value, dataType));
foreach (Attribute attrib in
field.GetCustomAttributes(true))
{
Console.WriteLine("\t{0}", attrib);
}
}
Console.WriteLine("Any key to quit.");
Console.ReadLine();
}
}
As can be seen above, we define our enum "Animals" and include the attribute names and values above each field of the enum, in the format: [AttributeType(Value)]. The attribute(s) should be followed by the definition of the enum element and its optional value. Note that even though the Attribute classes are named "XXXAttribute" we can still use the shorthand "XXX" in the element decoration.
Just below the enum definition, we add a class representing each Attribute which derives from Attribute. The ToString override is to make display easier. In practice, a developer would put each of these in it's own separate class file.
Finally in the Main program, we get the underlying type of the enum, and then iterate the FieldInfo objects via Reflection. The inner foreach loop uses the Convert class ChangeType method, which returns an Object with a specified type and whose value is equivalent to a specified object. Finally, the inner loop uses the GetCustomAttributes method to get an array of all the attributes. The boolean parameter specifies whether to search this member's inheritance chain to find the attributes.
Using this technique, you can store virtually any kind of metadata in an enum and read it out for use at runtime. The sample Visual Studio 2008 Solution includes the complete console app. If you do not have VS 2008, you should be able to just load the .csproj file in an earlier version of Visual Studio. |
 |
| Biography - Peter Bromberg |
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites. Please post questions at forums, not via email! |  |
|
|
 |
| Article Discussion: Using Attributes with Enums |
| Peter Bromberg posted at Tuesday, January 29, 2008 9:55 AM |
 | Original Article |
 |
| |
|
late binding with attributes/enums. |
| Troy Johnson replied to Peter Bromberg at Wednesday, November 11, 2009 4:17 PM |
 | Peter,
Read your post on using Attributes on Enums to yourself some metadata. This is exactly what I needed for something I was working on. Basically I wanted to bind a wpf combobox to an enum. Of course no spaces in an Enum so not very user friendly. Creating a "FriendlyText" attribute however which returns the attribute name with spaces between words solves this issue.
However, I also need it to do one other thing. My values in the enum actually represent Time intervals. So you would see values such as "1 Day", "5 Day", "10 Day" in the enum. I created another attribute called TimeValue which gives me an integer for the numeric part of the string. So the TimeValue for "1 Day" would be 1. Now I need to add values to the enum that aren't known at design time though. For instance I need to add a enum value called "Last Market Up Day". This refers to last day the dow was up. Of course this value can change daily, so I can't "hard code" that into my enum attribute. I tried using a variable wich was populated at runtime, but the enum attributes require a constant value.
Any ideas on how i might get around this?
Best Regards,
Troy |
 |
| |
|
| I am thinking on what you describe... |
| Peter Bromberg replied to Troy Johnson at Wednesday, November 11, 2009 5:39 PM |
 | Is there some rule that says you "jhave to" bind to an enum? Will a class do better? I'd think that would give you a bit more flexibility.
|
 |
| |
|
custom attributes and enums |
| Troy Johnson replied to Peter Bromberg at Wednesday, November 11, 2009 6:40 PM |
 | I liked the idea of the enum because I wouldn't have to create a class for each row (little more effecient). Also, the metadata would be with the enum values which I liked because I felt it would make the code easier to read (more maintanable). However, it seems i've out run the flexibility of the custom attributes with what i'm trying to do, so yes I think I will go with the a custom class for each row in the combobox i need.
Still you're solution will be great for the future when i simply need to bind to an enum but want a way to get spaces between the values so the values are more readable.
Thanks again,
Troy |
 |
| |
|
| Glad it was helpful to somebody |
| Peter Bromberg replied to Troy Johnson at Wednesday, November 11, 2009 8:08 PM |
 | I just wrote it up out of fascination with what you can do. Thanks for the nice post. |
 |
| |
|
|
|