To
work with any of these samples, you will need the
following: .........................................Microsoft
.NET SDK
The Reflection API allows a C#
program to inspect and manipulate itself. It can be used to effectively find all
the types in an assembly and/or dynamically invoke methods in an assembly. It
can at times even be used to emit Intermediate Language code on the fly so that
the generated code can be executed directly.
Reflection is also used to obtain
information about a class and its members. Reflection can be used to manipulate
other objects on the .NET platform.
The Reflection API uses the System.Reflection
namespace, with the Type
class to identify the Type of the Class being reflected, and fields of a
struct
or
enum
represented by the FieldInfo
class, Members of the reflected class represented by the MemberInfo
class, Methods of a reflected class represented by the MethodInfo
class, and parameters to Methods represented by the ParameterInfo
class.
The Activator
class's CreateInstance()
method is used to dynamically invoke instances on the fly. Dynamic Invocation is
very useful in providing a very late-binding architecture, where one component's
runtime can be integrated with other component runtimes.
We will illustrate the use of the
Reflection API in three different ways:
1. Obtaining Class and Type
Information from an Assembly
2. Obtaining Member Information
from a Class
3. Dynamically Invoking Methods
from Classes in an Assembly
Develop the Test Application
Before we start our forays into C#
Reflection and Dynamic Invocation, let us develop our test applications that
we'll use to test our Reflection code. Develop an interface called IBase.
ImplementationOne
and ImplementationTwo
are classes that implement the IBase
interface and are each compiled into
separate assemblies.
/** * A generic Structure */ struct StructOne { int x; double y;
double assign () { x = 10; y = 2.8; return x*y; } } }
3. Compile the Test Application as a Library
(DLL) : ImplementationOne.DLL
MS-DOS Command Prompt
H:\gopalan\Reflection>
H:\gopalan\Reflection>csc /target:library ImplementationOne.cs IBase.cs
Microsoft (R) C# Compiler Version 7.00.8905 [NGWS runtime 2000.14.1812.10]
Copyright (C) Microsoft Corp 2000. All rights reserved.
H:\gopalan\Reflection>
H:\gopalan\Reflection>csc /target:library ImplementationTwo.cs IBase.cs
Microsoft (R) C# Compiler Version 7.00.8905 [NGWS runtime 2000.14.1812.10]
Copyright (C) Microsoft Corp 2000. All rights reserved.
H:\gopalan\Reflection>
Obtaining All
Classes and Their Type Information from an Assembly
1. Develop an Application that Reflects Types:
ReflectTypes
/** * File: ReflectTypes.cs * Article: C# Reflection and Dynamic
Method Invocation * Copyright (c) 2000, Gopalan Suresh Raj. All Rights Reserved. * Compile with: csc ReflectTypes * Run as: ReflectTypes <library> * eg., ReflectTypes ImplementationOne.dll */
using System; using System.Reflection;
/** * Develop a class that can Reflect all the Types available in an Assembly */ class ReflectTypes {
public static void Main (string[] args) {
// List all the types in the assembly that is passed in as a parameter Assembly assembly = Assembly.LoadFrom (args[0]);
// Get all Types available in the assembly in an array Type[] typeArray = assembly.GetTypes ();
Console.WriteLine ("The Different Types of Classes Available in {0} are:", args[0]); Console.WriteLine ("_____"); // Walk through each Type and list their Information foreach (Type type in typeArray) { // Print the Class Name Console.WriteLine ("Type Name : {0}", type.FullName); // Print the name space Console.WriteLine ("Type Namespace : {0}", type.Namespace); // Print the Base Class Name Console.WriteLine ("Type Base Class : {0}", (type.BaseType != null)?type.BaseType.FullName:"No Base Class Found..."); Console.WriteLine ("_____"); } } }
2. Compile and Run ReflectTypes (ReflectTypes.EXE)
on Our Test
Library (ImplementationOne.DLL)
MS-DOS Command Prompt
H:\gopalan\Reflection>
H:\gopalan\Reflection>csc ReflectTypes.cs
Microsoft (R) C# Compiler Version 7.00.8905 [NGWS runtime 2000.14.1812.10]
Copyright (C) Microsoft Corp 2000. All rights reserved.
H:\gopalan\Reflection>
H:\gopalan\Reflection>ReflectTypes ImplementationOne.dll
The Different Types of Classes Available in ImplementationOne.dll are:
_____
Type Name : com.icommware.ColorEnumeration
Type Namespace : com.icommware
Type Base Class : System.Enum
_____
Type Name : com.icommware.IBase
Type Namespace : com.icommware
Type Base Class : No Base Class Found...
_____
Type Name : com.icommware.StructOne
Type Namespace : com.icommware
Type Base Class : System.ValueType
_____
Type Name : com.icommware.ImplementationOne
Type Namespace : com.icommware
Type Base Class : System.Object
_____
H:\gopalan\Reflection>
Obtaining Member
Information from a Class
1. Develop an Application that Reflects
Methods: ReflectMethods
/** * File: ReflectMethods.cs * Article: C# Reflection and Dynamic Method Invocation * Copyright (c) 2000, Gopalan Suresh Raj. All Rights Reserved. * Compile with: csc ReflectMethods */
using System; using System.Reflection;
namespace com.icommware {
/** * An enumeration of Account Types */ enum AccountEnumeration { CHECKING = 1, SAVINGS = 2, }
/** * A Class that implements the IBase interface */ class ImplementationTwo : IBase { string remark = "Remark of ImplementationTwo"; static int DELTAFACTOR = 100;
/** * A generic Structure */ struct StructTwo { double x; int y;
double assign () { x = 8.2; y = 10; return x*y; } } }
/** * Develop a class that can Reflect all the Types available in an Assembly */ class ReflectMethods {
public static void Main (string[] args) {
// retrieve information about AccountEnumeration Console.WriteLine ("Names and Values of the com.icommware.AccountEnumeration are:"); Type type = typeof (com.icommware.AccountEnumeration );
// Create an instance of AccountEnumeration in Memory object accountEnum = Activator.CreateInstance (type);
// List the names and values available in the AccountEnumeration enum foreach (FieldInfo fieldInfo in type.GetFields (BindingFlags.LookupAll)) { object value = fieldInfo.GetValue (accountEnum); Console.WriteLine ("{0} = {1}", fieldInfo, value); } Console.WriteLine ("_____");
// retrieve information about ImplementationTwo Class Console.WriteLine ("The Members of the
com.icommware.ImplementationTwo Class are:"); type = typeof (com.icommware.ImplementationTwo);
// List the members of the ImplementationTwo Class foreach (MemberInfo memberInfo in type.GetFields (BindingFlags.LookupAll)) { Console.WriteLine ("{0}", memberInfo); } Console.WriteLine ("_____");
// Walk through the methods of the ImplementationTwo Class Console.WriteLine ("The Methods of the
com.icommware.ImplementationTwo Class are:"); foreach (MethodInfo methodInfo in type.GetMethods (BindingFlags.LookupAll)) { // Print the Method Signature Console.WriteLine ("{0}", methodInfo); // Walk through the method parameters foreach (ParameterInfo parameterInfo in methodInfo.GetParameters ()) { // Print the Parameter Type and the Parameter Name Console.WriteLine (" Param: {0} {1}", parameterInfo.ParameterType, parameterInfo.Name); } Console.WriteLine ("_____"); }
// retrieve information about StructTwo Class Console.WriteLine ("The Members of the
com.icommware.StructTwo Class are:"); type = typeof (com.icommware.StructTwo);
// List the members of the StructTwo Class foreach (MemberInfo memberInfo in type.GetFields (BindingFlags.LookupAll)) { Console.WriteLine ("{0}", memberInfo); } Console.WriteLine ("_____"); // Walk through the methods of the StructTwo Class Console.WriteLine ("The Methods of the
com.icommware.StructTwo Class are:"); foreach (MethodInfo methodInfo in type.GetMethods (BindingFlags.LookupAll)) { // Print the Method Signature Console.WriteLine ("{0}", methodInfo); // Walk through the method parameters foreach (ParameterInfo parameterInfo in methodInfo.GetParameters ()) { // Print the Parameter Type and the Parameter Name Console.WriteLine (" Param: {0} {1}", parameterInfo.ParameterType, parameterInfo.Name); } Console.WriteLine ("_____"); } } }
2. Compile and Run ReflectMethods (ReflectMethods.EXE)
MS-DOS Command Prompt
H:\gopalan\Reflection>
H:\gopalan\Reflection>csc ReflectMethods.cs IBase.cs Microsoft (R) C# Compiler Version 7.00.8905 [NGWS runtime 2000.14.1812.10]
Copyright (C) Microsoft Corp 2000. All rights reserved.
H:\gopalan\Reflection>ReflectMethods Names and Values of the com.icommware.AccountEnumeration are:
Int32 value__ = 0
com.icommware.AccountEnumeration CHECKING = 1
com.icommware.AccountEnumeration SAVINGS = 2
_____
The Members of the com.icommware.ImplementationTwo Class are:
System.String remark
Int32 DELTAFACTOR
_____
The Methods of the com.icommware.ImplementationTwo Class are:
Double compute (Int32, Double)
Param: Int32 param1
Param: Double param2
_____
System.String execute (System.String)
Param: System.String data
_____
Void Finalize ()
_____
Int32 GetHashCode ()
_____
Boolean Equals (System.Object)
Param: System.Object obj
_____
System.String ToString ()
_____
System.Type GetType ()
_____
System.Object MemberwiseClone ()
_____
The Members of the com.icommware.StructTwo Class are:
Double x
Int32 y
_____
The Methods of the com.icommware.StructTwo Class are:
Void Finalize ()
_____
Int32 GetHashCode ()
_____
Boolean Equals (System.Object)
Param: System.Object obj
_____
System.String ToString ()
_____
Double assign ()
_____
System.Type GetType ()
_____
System.Object MemberwiseClone ()
_____
H:\gopalan\Reflection>
Dynamically invoking methods
from a class in an Assembly
We use Reflection to open all the Assemblies on
the command line, search for Classes that implement the com.icommware.IBase
interface, create an instance of that class and invoke the compute()
method on the assembly.
1. Develop an Application that dynamically
invokes methods from an Assembly
/** * File: DynamicInvocation.cs * Article: C# Reflection and Dynamic Method Invocation * Copyright (c) 2000, Gopalan Suresh Raj. All Rights Reserved. * Compile with: csc DynamicInvocation.cs * Run As: DynamicInvocation <library | Application...> * eg., DynamicInvocation ImplementationOne.DLL ReflectMethods.EXE */
using System; using System.Reflection; using com.icommware;
class DynamicInvocation {
public static void invokeProcess (string assemblyName) { Console.WriteLine ("Loading {0} into memory...", assemblyName); Assembly assembly = Assembly.LoadFrom (assemblyName);
// Walk through each type in the assembly foreach (Type type in assembly.GetTypes ()) { // Pick up a class if (type.IsClass == true) { Console.WriteLine ("...Found Class : {0}", type.FullName);
// If it does not implement the IBase Interface, skip it if (type.GetInterface ("com.icommware.IBase") == null) { continue; }
// If however, it does implement the IBase Interface, // create an instance of the object object ibaseObject = Activator.CreateInstance (type);
// Create the parameter list object[] arguments = new object [] {10, 17.11}; object result; // Dynamically Invoke the Object Console.WriteLine ("......Dynamically Invoking compute() on {0} Class", type.FullName); result = type.InvokeMember ("compute", BindingFlags.Default | BindingFlags.InvokeMethod, null, ibaseObject, arguments);
Console.WriteLine ("......Result is: {0}", result); } } }
public static void Main (string[] args) { foreach (string argument in args) { invokeProcess (argument); } }
}
2. Compile and Run DynamicInvocation (DynamicInvocation.EXE)
MS-DOS Command Prompt
H:\gopalan\Reflection>
H:\gopalan\Reflection>csc DynamicInvocation.cs IBase.cs
Microsoft (R) C# Compiler Version 7.00.8905 [NGWS runtime 2000.14.1812.10]
Copyright (C) Microsoft Corp 2000. All rights reserved.
H:\gopalan\Reflection>DynamicInvocation ImplementationOne.DLL ReflectMethods.EXE Loading ImplementationOne.DLL into memory...
...Found Class : com.icommware.ImplementationOne
Invoking ImplementationOne...
......Dynamically Invoking compute() on com.icommware.ImplementationOne Class
ImplementationOne's compute() method invoked...
......Result is: 1711
Loading ReflectMethods.EXE into memory...
...Found Class : com.icommware.ImplementationTwo
Invoking ImplementationTwo ...
......Dynamically Invoking compute() on com.icommware.ImplementationTwo Class
ImplementationTwo's compute() method invoked...
......Result is: 17110
...Found Class : ReflectMethods