C#: Custom Attributes



In C# we've got a mechanism called attributes, which we use to provide extra information about certain elements within our code.

An example of attributes available within C# is the XmlAttribute/XmlRoot/XmlElement attributes - which we use in conjunction with the XmlSerializer class - used to serialize objects to XML.

 
using System;
using System.IO;
using System.Xml.Serialization;
 
public class friend
{
    [XmlAttribute()]
    public String firstname
    {
        get;
        set;
    }
 
    [XmlAttribute()]
    public String lastname
    {
        get;
        set;
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        friend f = new friend
        {
            firstname = "John",
            lastname = "Doe"
        };
 
        using (StreamWriter sw = new StreamWriter(@"c:\abc.xml"))
        {
            XmlSerializer xs = new XmlSerializer(typeof(friend));
            xs.Serialize(sw.BaseStream, f);
        }
    }
}
 

Internally the XmlSerializer class uses reflection to process the attributes we assigned to our class - in this instance we're telling the serializer to format our properties as xml attributes within the XML.

But what if we want to create our own custom attributes? Lets imagine we want to create attributes that defines certain constraints on our classes (not ideal, but useful as an example of how to create/retrieve custom attributes)

Basically we need to inherit from the Attribute class and define on which elements we wish to make our attribute available to:
 
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class Constraint : Attribute
{
    public Boolean Unique
    {
        get;
        set;
    }
 
    public Boolean Required
    {
        get;
        set;
    }
}
 

An example of how to use our custom attribute:
 
public class post
{
    [Constraint(Unique = true, Required = true)]
    public String title
    {
        get;
        set;
    }
 
    [Constraint(Required = true)]
    public Int32 age
    {
        get;
        set;
    }
}
 

To process/read our custom attribute we use the reflection classes like this:
 
public class posts : List<post>
{
    // Hide inherited member "Add"
	public new void Add(post item)
    {
		// Get properties within our class
        PropertyInfo[] properties = item.GetType().GetProperties();
        foreach (PropertyInfo property in properties)
        {
            object o = property.GetValue(item, null);
 
            // Get custom attributes of type Constraint
			object[] attributes = property.GetCustomAttributes(typeof(Constraint), true);
 
            foreach (Constraint attribute in attributes)
            {
                // Check Required Constraint
				if (attribute.Required)
                {
                    if (o == null)
                        throw new Exception(String.Concat(property.Name, " property required"));
 
                    else if (o is int)
                    {
                        if (((int)o) == 0)
                            throw new Exception(String.Concat(property.Name, " property required"));
                    }
                }
 
				// Check Unique Constraint
                if (attribute.Unique)
                {
					// linq query testing for duplicate entries
                    if ((from p in this
                         where p.GetType().GetProperty(property.Name).GetValue(p, null) == o
                         select p).Count() > 0)
                        throw new Exception(String.Concat(property.Name, " property unique violation"));
                }
            }
        }
 
        base.Add(item);
    }
}
 

In the example we're checking for the constraint custom attribute on the properties of our class, but alternatively we may also add/process custom attributes on classes/structs/enum etc (see the AttributeTargets enum)







Post comment

Name *
Email
Title
Body *
Security Code
*
* Required fields

Latest Posts

Be the best stalker you can be


2011-12-13 22:33:54

Syntactic sugar (C#): Enum


2011-08-04 16:50:18

Top 5 posts

Simple WYSIWYG Editor


Creating a WYSIWYG textbox for your website is actually quite simple.
2007-02-01 12:00:00

Moving items between listboxes in ASP.net/PHP example


Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
2008-06-12 17:07:43

Cross Browser Issues: Firefox Word Wrapping


Firefox word wrapping issues
2008-06-09 09:51:21

Populate a TreeView Control C#


Populate a TreeView control in a windows application.
2009-08-27 16:01:03

C# YouTube : Google API


Post on how to integrate with YouTube using the Google Data API
2011-03-12 08:37:51