Pages

Monday, November 3, 2008

REFLECTION AND ATTRIBUTES (Part One)

Today I decided to post a series of tutorials about Reflection and Attributes from the free chapter of Core C# book.  So I'm going to start it with Reflection (Creating a Type Object).  Read the first part of the chapter below:

 

19.1 Reflection

  In general terms, reflection is the ability of a system to reason and act upon itself.  More specifically, .NET supports reflection as a mechanism for reading an assembly’s metadata in order to glean information about types within the assembly. It has many uses. For example, VS.NET uses it to implement Intellisense; and .NET object serialization relies on reflection to identify whether a type can be serialized (by looking for the SerializableAttribute) and which of its members are serializable.

While reflection is a powerful technique, it’s not difficult to understand. Think of the reflection API as a set of methods that can be applied at each level of the .NET coding hierarchy. The Assembly.GetTypes method yields all the types in an assembly
as System.Type objects. The System.Type class, in turn, exposes methods that return a specific type’s properties, methods, constructors, events, and fields. At an even more granular level, you can then examine the parameters of a method or constructor.

Before a type (class, struct, array, enum, generic types, value types, or interface) can be reflected, a Type reference must be acquired for the type. This reference is the key that unlocks the door to the .NET reflection API.

 

The System.Type class

System.Type is an abstract class whose members provide the primary means of accessing the metadata that describes a type.

Syntax:
public abstract class Type : MemberInfo, _Type, IReflect

The Type class inherits from the MemberInfo class and two interfaces—_Type and IReflect. Of these, MemberInfo is of particular interest. It serves as the base class for some of the most important classes in the reflection namespace, and defines
many of the methods and properties that provide information about a type’s members and attributes. We’ll look at it in detail shortly.


Creating a Type Object

In order to use reflection to examine a type’s metadata, it is first necessary to obtain a reference to a Type object that is associated with the type to be reflected. There are several ways to obtain a Type object reference. The choice varies depending on whether the object is being created from a type’s definition or an instance of the type.  To illustrate the first case, consider the following code segment that lists the methods for the System.Object class.

// (1) Get Type for System.Object definition
          
Type obType = typeof(System.Object);
            // Alternative: Type obType= Type.GetType("System.Object");
            // (2) Call a method to return list of methods for Object
          
MethodInfo[] mi = obType.GetMethods();
            for(int i = 0; i < mi.Length; i++)
            {
                MethodInfo myMethodInfo = (MethodInfo)mi[i];
                Console.WriteLine("Method name: {0}({1})",
                myMethodInfo.Name, myMethodInfo.ReturnType);
                /* Output:
                Method Name: GetHashCode (System.Int32)
                Method Name: Equals (System.Boolean)
                (remaining methods listed here)
                */
          
}


This example uses the C# typeof operator to obtain a Type reference. Alternatively, the Type.GetType method, which accepts a type’s name as a string value, could be used. Once the Type object is obtained, the Type.GetMethods method is called to return an array of MethodInfo objects that represent the methods for the type. The Name and ReturnType properties of the MethodInfo class expose the name and return type of each method.  To acquire a Type object reference for an instance of a type—rather than its definition—use the GetType method that all types inherit from System.Object:

Device myDevice = newDevice(); // Create class instance
Type t = myDevice.GetType(); // GetType reference
// Reflection can also be used on value types
int[] ages = { 22, 43, 55 };

Type ageType = ages.GetType();
Console.WriteLine(ageType.Name); // Output: Int32[]

Later in this section, we’ll see how to use the Assembly.GetTypes and Module.GetTypes methods to obtain Type object references for types in an assemblyand module, respectively.

So there it goes that's the first part of chapter 19 of the book Core C#, on the next series I am going to post the System.Type Members

Related topic:

REFLECTION AND ATTRIBUTES (Part Two)

Related Post: