Article

This is in continuation to Reflection in .NET - Part 2

Querying the fields for their attached attributes

Consider a library app that has the entities like Book, Student, etc. Now you can use attributes to associate the names of the database tables and columns with the .NET classes and their member fields. For this purpose, define a class named DatabaseAttribute derived from the System.Attribute class.

Make the Table property of DatabaseAttribute class a named parameter and set its default value to Book so that the attribute's user doesn't need to key in this value most of the time as most of the member fields in this app belong to the Book entity. Now if the user wants to provide some value other than Book, she can use the named parameter like this: Table="Student"

Whenever an attribute is used, we want that the user must specify the column name corresponding to the target member field. Therefore, make the Column property as the positional parameter.

using System;
using System.Reflection;
public class DatabaseAttribute : System.Attribute {
    string column, table;
    public string Column { get { return column; } }
    public string Table {
        get { return table; }
        set { table = value; }
    }
    public DatabaseAttribute (string column) {
        this.column = column;
        this.table = “Book”;
    }
}

class Student {

    //Attach the DatabaseAttribute to the 'code' field. The studentCode is the 
    //corresponding column name. Table is the named parameter and Student is its value.
    [Database ("studentCode", Table="Student")]
    public int code;

    [Database ("studentName", Table="Student")]
    public string name;

    //Methods
}

class Book {
    //only mandatory info. is passed, no named parameters are passed
    [Database ("isbnCode")]
    public int code;

    [Database ("bookAuthor")]
    public string author;
    ...
}

We will use reflection to query the fields of Student type about its attached attributes.

public class QueryingAttributesDemo3 {
    public static void Main() {
        //Obtain the Type object associated with the Student class
        Type student = typeof(Student);

        //Each FieldInfo object encapsulates the information about a field defined  
        //in the Student class
        FieldInfo[] studentFields = student.GetFields();

        //Iterate through the array of FieldInfo objects and display the attributes 
        //associated with each field
        foreach (FieldInfo field in studentFields) {
            Object[] attributes = field.GetCustomAttributes(false);
            foreach (Object attrib in attributes) {
                DatabaseAttribute dba = (DatabaseAttribute) attrib;
                Console.WriteLine("{0} field declared in {1} class maps to the {2} 
                                    column of {3} table", field.Name, 
                                    field.DeclaringType, dba.Column, dba.Table);
                //Do the database operations such as "insert into this table..."
            }
        }        //End of foreach
    }            //End of Main
}                //End of class

Output
code field declared in Student class maps to the studentCode column of Student table
name field declared in Student class maps to the studentName column of Student table

Similarly, you can query the fields of Book type about its attached attributes.

Querying the classes for their attached attributes

Mark the Alpha class with the Serializable and Obsolete attributes.

[Obsolete]          //regular custom attribute
[Serializable]      //pseudo custom attribute
public class Alpha { ... }

//Query for custom attributes on Alpha class. The GetCustomAttributes() method is 
//called on the Type object associated with the Alpha class.
Type type = typeof(Alpha);
foreach (object obj in type.GetCustomAttributes(false))
    Console.WriteLine(obj);

Output
System.ObsoleteAttribute

Note that the reflection has returned only the regular custom ObsoleteAttribute. It has not returned the pseudo-custom SerializableAttribute.

For Part 4, click this link: Reflection in .NET - Part 4