Wednesday, September 2, 2009

Reflection in C# 1

Reflection
For the attributes in the metadata to be useful, you need a way to access them--ideally during runtime. The classes in the Reflection namespace, along with the System.Type and System.TypedReference classes, provide support for examining and interacting with the metadata.
Reflection is generally used for any of four tasks: 

Viewing metadata
This might be used by tools and utilities that wish to display metadata. 

Performing type discovery
This allows you to examine the types in an assembly and interact with or instantiate those types. This can be useful in creating custom scripts. For example, you might want to allow your users to interact with your program using a script language, such as JavaScript, or a scripting language you create yourself. 

Late binding to methods and properties
This allows the programmer to invoke properties and methods on objects dynamically instantiated based on type discovery. This is also known as dynamic invocation. 

Creating types at runtime (Reflection Emit)
The ultimate use of reflection is to create new types at runtime and then to use those types to perform tasks. You might do this when a custom class, created at runtime, will run significantly faster than more generic code created at compile time.

Viewing MetaData
In this section, you will use the C# Reflection support to read the metadata in the MyMath class.
Start by initializing an object of the type MemberInfo. This object, in the System.Reflection namespace, is provided to discover the attributes of a member and to provide access to the metadata:
System.Reflection.MemberInfo inf = typeof(MyMath);
Call the typeof operator on the MyMath type, which returns an object of type Type, which derives from MemberInfo.
TIP: The Type class is the root of the reflection classes. Type encapsulates a representation of the type of an object. The Type class is the primary way to access metadata. Type derives from MemberInfo and encapsulates information about the members of a class (e.g., methods, properties, fields, events, etc.).
The next step is to call GetCustomAttributes on this MemberInfo object, passing in the type of the attribute you want to find. You get back an array of objects, each of type BugFixAttribute:
object[] attributes;
attributes =
   inf.GetCustomAttributes(typeof(BugFixAttribute),false);
You can now iterate through this array, printing out the properties of the BugFixAttribute object. Example 1  replaces the Tester class from Example 2. 

Example 2: Using reflection
public static void Main(  )
{
    MyMath mm = new MyMath(  );
    Console.WriteLine("Calling DoFunc(7). Result: {0}",
        mm.DoFunc1(7));
    // get the member information and use it to
    // retrieve the custom attributes
    System.Reflection.MemberInfo inf = typeof(MyMath);
    object[] attributes;
    attributes =
       inf.GetCustomAttributes(
            typeof(BugFixAttribute), false);
    // iterate through the attributes, retrieving the
    // properties
    foreach(Object attribute in attributes)
    {
        BugFixAttribute bfa = (BugFixAttribute) attribute;
        Console.WriteLine("\nBugID: {0}", bfa.BugID);
        Console.WriteLine("Programmer: {0}", bfa.Programmer);
        Console.WriteLine("Date: {0}", bfa.Date);
        Console.WriteLine("Comment: {0}", bfa.Comment);
    }
}
Output:
Calling DoFunc(7). Result: 9.3333333333333333
BugID: 121 Programmer: Jesse Liberty Date: 01/03/05 Comment:
BugID: 107 Programmer: Jesse Liberty Date: 01/04/05 Comment: Fixed off by one errors
When you put this replacement code into Example 1 in Attribute article( Working with custom attributes ) in Example-1 and run it, you can see the metadata printed as you'd expect.
Type Discovery
You can use reflection to explore and examine the contents of an assembly. You can find the types associated with a module; the methods, fields, properties, and events associated with a type, as well as the signatures of each of the type's methods; the interfaces supported by the type; and the type's base class.
To start, load an assembly dynamically with the Assembly.Load static method. The Assembly class encapsulates the actual assembly itself, for purposes of reflection. The signature for the Load method is:
public static Assembly.Load(AssemblyName)
For the next example, pass in the Core Library to the Load method. MsCorLib.dll has the core classes of the .NET Framework:
Assembly a = Assembly.Load("Mscorlib.dll");
Once the assembly is loaded, you can call GetTypes() to return an array of Type objects. The Type object is the heart of reflection. Type represents type declarations (classes, interfaces, arrays, values, and enumerations):
Type[] types = a.GetTypes();
The assembly returns an array of types that you can display in a foreach loop, as shown in Example 3. Because this listing uses the Type class, you will want to add a using statement for the System.Reflection namespace. 

Example 3: Reflecting on an assembly
namespace Programming_CSharp
{
    using System;
    using System.Reflection;
    public class Tester
    {
        public static void Main(  )
        {
            // what is in the assembly
            Assembly a = Assembly.Load("Mscorlib.dll");
            Type[] types = a.GetTypes(  );
            foreach(Type t in types)
            {
                    Console.WriteLine("Type is {0}", t);
            }
            Console.WriteLine(
               "{0} types found", types.Length);
        }
    }
}
The output from this would fill many pages. Here is a short excerpt:
Type is System.TypeCode
Type is System.Security.Util.StringExpressionSet
Type is System.Runtime.InteropServices.COMException
Type is System.Runtime.InteropServices.SEHException
Type is System.Reflection.TargetParameterCountException
Type is System.Text.UTF7Encoding
Type is System.Text.UTF7Encoding+Decoder
Type is System.Text.UTF7Encoding+Encoder
Type is System.ArgIterator
1426 types found
This example obtained an array filled with the types from the Core Library and printed them one by one. The array contained 1,426 entries on my machine.
Reflecting on a Type
You can reflect on a single type in the mscorlib assembly as well. To do so, extract a type from the assembly with the GetType() method, as shown in Example -4. 

Example 4: Reflecting on a type
namespace Programming_CSharp
{
    using System;
    using System.Reflection;
    public class Tester
    {
        public static void Main(  )
        {
            // examine a single object
             Type theType =
                Type.GetType(
                   "System.Reflection.Assembly");
             Console.WriteLine(
                "\nSingle Type is {0}\n", theType);
        }
    }   
}
Program Output:
Single Type is System.Reflection.Assembly
Finding all type members
You can ask the Assembly type for all its members using the GetMembers() method of the Type class, which lists all the methods, properties, and fields, as shown in Example  5. 

Example 5: Reflecting on the members of a type
namespace Programming_CSharp
{
   using System;
   using System.Reflection;
   public class Tester
   {
      public static void Main(  )
      {
         // examine a single object
         Type theType =
            Type.GetType(
               "System.Reflection.Assembly");
         Console.WriteLine(
            "\nSingle Type is {0}\n", theType);
         // get all the members
         MemberInfo[] mbrInfoArray =
            theType.GetMembers(  );
         foreach (MemberInfo mbrInfo in mbrInfoArray )
         {
            Console.WriteLine("{0} is a {1}",
               mbrInfo, mbrInfo.MemberType);
         }
      }
   }   
}
Once again the output is quite lengthy, but within the output you see fields, methods, constructors, and properties, as shown in this excerpt:
Boolean IsDefined(System.Type, Boolean) is a Method
System.Object[] GetCustomAttributes(Boolean) is a Method
System.Object[] GetCustomAttributes(System.Type, Boolean) is a Method
System.Security.Policy.Evidence get_Evidence( ) is a Method
System.String get_Location( ) is a Method
Finding type methods
You might want to focus on methods only, excluding the fields, properties, and so forth. To do so, remove the call to GetMembers():
MemberInfo[] mbrInfoArray =
    theType.GetMembers(BindingFlags.LookupAll);
and add a call to GetMethods():
mbrInfoArray = theType.GetMethods(  );
The output now is nothing but the methods:
Output (excerpt):
Boolean Equals(System.Object) is a Method
System.String ToString( ) is a Method
System.String CreateQualifiedName(
   System.String, System.String) is a Method
Boolean get_GlobalAssemblyCache( ) is a Method
Finding particular type members
Finally, to narrow it down even further, you can use the FindMembers method to find particular members of the type. For example, you can narrow your search to methods whose names begin with the letters Get.
To narrow the search, use the FindMembers method, which takes four parameters: MemberTypes, BindingFlags, MemberFilter, and object.
MemberTypes A MemberTypes object that indicates the type of the member to search for. These include All, Constructor, Custom, Event, Field, Method, Nestedtype, Property, and TypeInfo. You will also use the MemberTypes.Method to find a method.
BindingFlags An enumeration that controls the way searches are conducted by reflection. There are a great many BindingFlag values, including IgnoreCase, Instance, Public, Static, and so forth.
MemberFilter A delegate that is used to filter the list of members in the MemberInfo array of objects. The filter you'll use is Type.FilterName, a field of the Type class used for filtering on a name.
Object A string value that will be used by the filter. In this case you'll pass in "Get*" to match only those methods that begin with the letters Get.
The complete listing for filtering on these methods is shown in Example  6. 

Example 6: Finding particular members
namespace Programming_CSharp
{
   using System;
   using System.Reflection;
   public class Tester
   {
      public static void Main(  )
      {
         // examine a single object
         Type theType = Type.GetType(
            "System.Reflection.Assembly");
         // just members which are methods beginning with Get
         MemberInfo[] mbrInfoArray =
            theType.FindMembers(MemberTypes.Method,
               BindingFlags.Public |
               BindingFlags.Static |
               BindingFlags.NonPublic |
               BindingFlags.Instance |
               BindingFlags.DeclaredOnly,
               Type.FilterName, "Get*");
         foreach (MemberInfo mbrInfo in mbrInfoArray )
         {
            Console.WriteLine("{0} is a {1}",
               mbrInfo, mbrInfo.MemberType);
         }
      }
   }
}
Output (excerpt):
System.Type[] GetTypes( ) is a Method
System.Type[] GetExportedTypes( ) is a Method
System.Type GetType(System.String, Boolean) is a Method
System.Type GetType(System.String) is a Method
System.Reflection.AssemblyName GetName(Boolean) is a Method
System.Reflection.AssemblyName GetName( ) is a Method
Late Binding
Once you have discovered a method, it's possible to invoke it using reflection. For example, you might like to invoke the Cos( ) method of System.Math, which returns the cosine of an angle. 

TIP: You could, of course, call Cos( ) in the normal course of your code, but reflection allows you to bind to that method at runtime. This is called late-binding and offers the flexibility of choosing at runtime which object you will bind to and invoking it programmatically. This can be useful when creating a custom script to be run by the user or when working with objects that might not be available at compile time. For example, by using late-binding, your program can interact with the spellchecker or other components of a running commercial word processing program such as Microsoft Word.
To invoke Cos( ), you will first get the Type information for the System.Math class:
Type theMathType = Type.GetType("System.Math");
With that type information, you could dynamically load an instance of a class by using a static method of the Activator class. Since Cos( ) is static, you don't need to construct an instance of System.Math (and you can't, since System.Math has no public constructor).
The Activator class contains four methods, all static, which you can use to create objects locally or remotely, or to obtain references to existing objects. The four methods are CreateComInstanceFrom, CreateInstanceFrom, GetObject, and CreateInstance:
CreateComInstanceFrom
Used to create instances of COM objects.
CreateInstanceFrom
Used to create a reference to an object from a particular assembly and type name.
GetObject
Used when marshaling objects.
CreateInstance
Used to create local or remote instances of an object.
For example:
Object theObj = Activator.CreateInstance(someType);
Back to the Cos( ) example, you now have one object in hand: a Type object named theMathType, which you created by calling GetType.
Before you can invoke a method on the object, you must get the method you need from the Type object, theMathType. To do so, you'll call GetMethod( ), and you'll pass in the signature of the Cos method.
The signature, you will remember, is the name of the method (Cos) and its parameter types. In the case of Cos( ), there is only one parameter: a double. However, Type.GetMethod takes two parameters. The first represents the name of the method you want, and the second represents the parameters. The name is passed as a string; the parameters are passed as an array of types:
MethodInfo CosineInfo =
   theMathType.GetMethod("Cos",paramTypes);
Before calling GetMethod, you must prepare the array of types:
Type[] paramTypes = new Type[1];
paramTypes[0]= Type.GetType("System.Double");
This code declares the array of Type objects and then fills the first element (paramTypes[0]) with a Type representing a double. Obtain the type representing a double by calling the static method Type.GetType( ), and passing in the string "System.Double".
You now have an object of type MethodInfo on which you can invoke the method. To do so, you must pass in the object to invoke the method on and the actual value of the parameters, again in an array. Since this is a static method, pass in theMathType. (If Cos( ) was an instance method, you could use theObj instead of theMathType.)
Object[] parameters = new Object[1];
parameters[0] = 45 * (Math.PI/180); // 45 degrees in radians
Object returnVal = CosineInfo.Invoke(theMathType,parameters);
TIP: Note that you've created two arrays. The first, paramTypes, holds the type of the parameters. The second, parameters, holds the actual value. If the method had taken two arguments, you'd have declared these arrays to hold two values. If the method did not take any values, you still would create the array, but you would give it a size of zero!
Type[] paramTypes = new Type[0];
Odd as this looks, it is correct.
Example  7 illustrates dynamically calling the Cos( ) method. 

Example 7: Dynamically invoking a method
namespace Programming_CSharp
{
   using System;
   using System.Reflection;
   public class Tester
   {
      public static void Main(  )
      {
         Type theMathType = Type.GetType("System.Math");
         // Since System.Math has no public constructor, this
         // would throw an exception.
         //Object theObj =
         //   Activator.CreateInstance(theMathType);
         // array with one member
         Type[] paramTypes = new Type[1];
         paramTypes[0]= Type.GetType("System.Double");
         // Get method info for Cos(  )
         MethodInfo CosineInfo =
            theMathType.GetMethod("Cos",paramTypes);
         // fill an array with the actual parameters
         Object[] parameters = new Object[1];
         parameters[0] = 45 * (Math.PI/180); // 45 degrees in radians
         Object returnVal =
            CosineInfo.Invoke(theMathType,parameters);
         Console.WriteLine(
            "The cosine of a 45 degree angle {0}",
            returnVal);
 
      }
   }
}
That was a lot of work just to invoke a single method. The power, however, is that you can use reflection to discover an assembly on the user's machine, to query what methods are available, and to invoke one of those members dynamically!
Reflection Emit
So far we've seen reflection used for three purposes: viewing metadata, type discovery, and dynamic invocation. You might use these techniques when building tools (such as a development environment) or when processing scripts. The most powerful use of reflection, however, is with reflection emit.
Reflection emit supports the dynamic creation of new types at runtime. You can define an assembly to run dynamically or to save itself to disk, and you can define modules and new types with methods that you can then invoke. 

TIP: The use of dynamic invocation and reflection emit should be considered an advanced topic. Most developers will never have need to use reflection emit.
To understand the power of reflection emit, you must first consider a slightly more complicated example of dynamic invocation.
Problems can have general solutions that are relatively slow and specific solutions that are fast. To keep things manageably simple, consider a DoSum( ) method, which provides the sum of a string of integers from 1-n, where n will be supplied by the user.
Thus, DoSum(3) is equal to 1+2+3, or 6. DoSum(10) is 55. Writing this in C# is very simple:
public int DoSum1(int n)
{
    int result = 0;
    for(int i = 1;i <= n; i++)
    {
        result += i;
    }
    return result;
}
The method simply loops, adding the requisite number. If you pass in 3, the method adds 1 + 2 + 3 and returns an answer of 6.
With large numbers, and when run many times, this might be a bit slow. Given the value 20, this method would be considerably faster if you removed the loop:
public int DoSum2(  )
{
    return 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20;
}
DoSum2 runs more quickly than DoSum1 does. How much more quickly? To find out, you'll need to put a timer on both methods. To do so, use a DateTime object to mark the start time and a TimeSpan object to compute the elapsed time.
For this experiment, you need to create two DoSum( ) methods; the first will use the loop and the second will not. Call each 1,000,000 times. (Computers are very fast, so to see a difference you have to work hard!) Then compare the times. Example 8 illustrates the entire test program. 

Example 8: Comparing loop to brute force
namespace Programming_CSharp
{
   using System;
   using System.Diagnostics;
   using System.Threading;
   public class MyMath
   {
      // sum numbers with a loop
      public int DoSum(int n)
      {
         int result = 0;
         for(int i = 1; i <= n; i++)
         {
            result += i;
         }
         return result;
      }
      // brute force by hand
      public int DoSum2(  )
      {
         return 1+2+3+4+5+6+7+8+9+10+11
            +12+13+14+15+16+17+18+19+20;
      }
   }
   public class TestDriver
   {
      public static void Main(  )
      {
         const int val = 20// val to sum
         // 1,000,000 iterations
         const int iterations = 1000000;
         // hold the answer
         int result = 0;
         MyMath m = new MyMath(  );           
         // mark the start time  
         DateTime startTime = DateTime.Now;
         // run the experiment
         for (int i = 0;i < iterations;i++)
         {
            result = m.DoSum(val);
         }
         // mark the elapsed time
         TimeSpan elapsed =
            DateTime.Now - startTime;
         // display the results
         Console.WriteLine(
            "Loop: Sum of ({0}) = {1}",
               val, result);
         Console.WriteLine(
            "The elapsed time in milliseconds is: " +
            elapsed.TotalMilliseconds.ToString(  ));
         // mark a new start time
         startTime = DateTime.Now;
         // run the experiment
         for (int i = 0;i < iterations;i++)
         {
            result = m.DoSum2(  );
         }
         // mark the new elapsed time
         elapsed = DateTime.Now - startTime;
         // display the results
         Console.WriteLine(
            "Brute Force: Sum of ({0}) = {1}",
               val, result);
         Console.WriteLine(
            "The elapsed time in milliseconds is: " +
            elapsed.TotalMilliseconds);
      }
   }
}
Output:
Loop: Sum of (20) = 210
The elapsed time in milliseconds is: 187.5
Brute Force: Sum of (20) = 210
The elapsed time in milliseconds is: 31.25
As you can see, both methods returned the same answer (one million times!), but the brute-force method was six times faster.
Is there a way to avoid the loop and still provide a general solution? In traditional programming, the answer would be no, but with reflection you do have one other option. You can, at runtime, take the value the user wants (20, in this case) and write out to disk a class that implements the brute-force solution. You can then use dynamic invocation to invoke that method.
There are at least three ways to achieve this result, each increasingly elegant. The third, reflection emit, is the best, but a close look at two other techniques is instructive.