Thursday, December 19, 2013

Custom Attributes in C#, Part 1

Intro, Including Why to Use Them

Attributes are yet another tool in your programming arsenal (hee hee, I said "arse"). If they're not already, we'll fix that right now! What is an attribute? It's a declarative way to associate information (usually called meta-information) with your code. What can you use attributes for? Just about anywhere you want to associate information with your code. Helpful answer huh? Like a judge and jury, I try. Here's a sample that might give you an idea:

    public enum VehicleBody
    {
        [Description("Sedan")]
        Sedan,
        [Description("Coupe")]
        Coupe,
        [Description("Station Wagon")]
        StationWagon,
        [Description("Crossover")]
        Crossover,
        [Description("Mini-van")]
        MiniVan,
    }

Above we have a simple enumeration that represents a few possible vehicle body types. Those attributes above each body type associate a specific user-friendly string with each entry. If we had a GUI driven by this information we could fill a drop-down list with those descriptions as the text, and the enumeration value as the value. Ooh, gotta love foreshadowing...

Example of Using a Built-in .Net Attribute, and Hey Some Reflection!


    
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using BlogAttributes;
using System.Reflection;

namespace BlogWebGui
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                var enumNames = Enum.GetNames(typeof(VehicleBody)).ToList();
                foreach (var enumName in enumNames)
                {
                    var type = typeof(VehicleBody);
                    var member = type.GetMember(enumName)[0];
                    var attribute = member.GetCustomAttribute(typeof(DescriptionAttribute));
                    var bodyDesription = ((DescriptionAttribute)attribute).Description;
                    uxVehicleBody.Items.Add(new ListItem() { Value = enumName, Text = bodyDesription });
                }
            }
        }
    }
}
The first code snippet above shows a rather simple section from an aspx page. Just a dropdownlist here.
The second code snippet is the code-behind for the aspx page. In the page load we populate the dropdownlist with the names and descriptions of our enums. Let's look at the important lines:
  1. "var enumNames..." This line just gets the names of our enumerated type values. All this means is we get a generic list containing the .ToString() representation of all members of our enumeration.
  2. "var member = type.GetMember(enumName)[0];" This sets the value of "member" to the correct value from the enumeration. For example, if enumName is set to "StationWagon", this code sets member to the value VehicleBody.StationWagon.
  3. "var attribute..." Here we set attribute to the attribute placed on the current enumeration value. In this case the attribute is of type DescriptionAttribute.
  4. "var bodyDescription..."Now we're getting the meat of it! Here we take the attribute we got above and grab its Description property to get that actual value we put into the attribute. So if we are looking at [Description("Station Wagon")]StationWagon, then this code returns the value "Station Wagon".
  5. "uxVehicleBody.Items..." Now we add each enumeration name and description attribute value to the dropdown list.
Here's the relevant portion of the html generated by the above code, which should help to further explain what the code is doing:
        


Pretty cool huh? Yeah I know this doesn't use up any less code than creating an array which contains the descriptive strings, but this code does have one large advantage over that approach: with enums and attributes, the lists will not get out of synch. With separate arrays holding values associated with enumerated types it is very easy to get the lists out of synch.

What's Next?

You might be thinking "has Peeticus misled me? I thought this article was about CUSTOM attributes, not using pre-canned ones?". Sorry, I only have so much space on each individual post and my attention span is being artificially shortened by an angry cat. Feel free to peek ahead though! We'll create our own custom attributes next week, I promise.

Resources

  • http://msdn.microsoft.com/en-us/library/aa288454%28v=vs.71%29.aspx

No comments:

Post a Comment