Wednesday, January 30, 2013

Creating an Attribute in C#

In C#, attribute is one of the common declarative technique that most of us is using into our application. Usually, we use the attribute to tag or flag a class, method or property in the form of object base recognition. It also simplify our determination in every object.

Furthermore, in C# there are lots of pre-defined attribute that we can embed into our application. One common sample is SerializableAttribute which flag/tag our class to participate in serialization/deserialization process. If however you would like to extend the attribute functionality and define your own, you can extend/inherit the attribute class from System namespace.

Please visit C# Flags Attribute blog before you continue. The reason is to let you explore the enumeration named Privilege.

Now, we are expecting that you already explore the Privilege enumeration form mentioned  blog above.

Let say for example you would like to define a scenario that gives your code-level to determine whether a class (or a stub object) can be deleted from database. See below our sample custom attribute.

public class SecurityAccess : Attribute
{
    public SecurityAccess()
    {
    }

    public SecurityAccess(Privilege privilege)
        : this()
    {
        this.Privilege = privilege;
    }

    public Privilege Privilege
    {
        get;
        set;
    }
}

What the class SecurityAccess is doing above is just simply handling the value for the Privilege enumeration. This property defines whether the class that declare this attribute has an enough level of privilege before doing necessary action in the database.

How to use custom attribute?

Now, in this section, we will going to guide you how to use the attribute we created above.

Suppose we have two class that inherits from one object. Let's call them Animal, and the two other class in Cat and Dog. See below implementation.

public class Animal
{
    public bool IsDeletable
    {
        get;
        protected set;
    }
}

public class Cat : Animal
{
    public Cat()
    {
    }
}

public class Dog : Animal
{
    public Dog()
    {
    }
}

The Dog and Cat is an Animal base on our implementation. With the use of our custom attribute named SecurityPrivilege, we can declare each privilege in every class. Suppose we would like different breed of Cat cannot be deleted from our database, then we can declare our custom attribute like below.

[SecurityAccess(Privilege = Privilege.Read | Privilege.Write | Privilege.Create)]
public class Cat : Animal
{
    public Cat()
    {

    }
}

And the Dog breed is deletable. See below.

[SecurityAccess(Privilege = Privilege.Read | Privilege.Write | Privilege.Create | Privilege.Delete)]
public class Dog : Animal
{
    public Dog()
    {

    }
}

How to access an attribute value declared in the class/method and other object?

Now, in this section, we will going to guide you how to access the value of the attribute per class level.

In C#, the only way to get the attribute value is to use Reflection. First, we need to get the current type of the object, from there check if there are declared custom attributes and determine the attribute type. If its match the attribute we're looking for, then that is the custom attribute we had created. See below the process.

protected T GetCustomAttribute<T>(object @object)
{
    if (!object.ReferenceEquals(@object, null))
    {
        var type = @object.GetType();
        var attrs = type.GetCustomAttributes(false);
        if (attrs.Length > 0)
        {
            foreach (var attr in attrs)
            {
                if (attr is T)
                {
                    return (T)(object)attr;
                }
            }
        }
    }
    return default(T);
}

What the code is doing above is to simply return the embedded attribute in the object you passed in the parameter named @object. If there is no attribute found, then it will return null. Best to place this code in the Animal base class so both derive class can use it.

And now, in the construction of Dog and Cat class, you should call the method directly from there.

public Dog()
{
    var attr = this.GetCustomAttribute<SecurityAccess>(this);
    base.IsDeletable = (attr.Privilege & Privilege.Delete) == Privilege.Delete;
}

public Cat()
{
    var attr = this.GetCustomAttribute<SecurityAccess>(this);
    base.IsDeletable = (attr.Privilege & Privilege.Delete) == Privilege.Delete;
}

Now, in the base class IsDeletable property, we then set it depends on the privilege level we declared on the class.

Please note that we can override the attribute value declared in the base class into derive class. So if you want that the Siamese Cat breed be deletable, you can declare your own SecurityAccess attribute in Siamese class.

That's all about this blog. Please follow us so you will get more interesting topics soon.

Please visit Microsoft documentation for further details.

No comments:

Post a Comment

Place your comments and ideas