0% found this document useful (0 votes)
67 views28 pages

Pluggable Components (Part I) : Brief Overview of Assembly & Modules

The document discusses reflection in .NET, which allows an application to examine its own structure at runtime. It provides an overview of assemblies, modules, and types in .NET. Reflection allows loading assemblies dynamically, getting type information, instantiating types, and invoking methods. The document includes a sample C# program that uses reflection to load an assembly and print the names of its contained types.

Uploaded by

hayabusa_ryo
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
67 views28 pages

Pluggable Components (Part I) : Brief Overview of Assembly & Modules

The document discusses reflection in .NET, which allows an application to examine its own structure at runtime. It provides an overview of assemblies, modules, and types in .NET. Reflection allows loading assemblies dynamically, getting type information, instantiating types, and invoking methods. The document includes a sample C# program that uses reflection to load an assembly and print the names of its contained types.

Uploaded by

hayabusa_ryo
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 28

Reflection in .

Net – Develop & Use Dynamically


Pluggable Components (Part I)
One of the highlights of .Net and its Common Language Runtime (CLR) is its support
for metadata. What does it actually mean is that with each assembly (.exe or .dll),
.Net compilers store information about the types it contains. Using this metadata you
can load an assembly dynamically (at runtime), get information about its containing
types, instantiate these types and can even generate, compile and run some code at
runtime!

This is an amazing power that .Net gives you through its reflection technology, which
provides the ground to develop and use the pluggable components during the
execution of application. Before we go on to further details, lets have some brief
review of .Net assemblies, modules, types and how CLR manages them.

Brief overview of Assembly & Modules


An assembly is a physical collection of related modules and types used for
deployment. There are two important points in this definition:

1. While namespace is a logical collection of related types, an assembly is a


physical collection of related types. Strictly speaking, an assembly exists in file
system in the form of .exe or .dll file.
2. An assembly is a deployment unit of your code. We deploy our application in
the form of assemblies.

At this point, I think the concept of assembly is quite clear to you; but one thing that
might be pondering in your mind is what actually the module mean then? In fact, an
assembly may contain one or more modules. A module is again a physical collection
of types.

You can compile some part of application or component in module (which gets stored
in the file system as .netmodule file) and later combine all the related modules to
make an assembly. So what exactly is the difference between a module and
assembly? An assembly essentially contains something called ‘Manifest’ while a
module does not. Finally, the manifest of an assembly contains the metadata with
following information:

 Versioning information of an assembly


 An entry for each file that constitutes the assembly
 An entry for each type in the assembly
 An entry for each resources or other assemblies referenced (used) by this
assembly

Most of the times, developers do not use multiple modules to pack their types but just
a single module per assembly. Hence, an assembly usually contain types (classes,
interfaces, structures, events) while types contain members (like variables, methods,
properties).

Reflection
The dictionary meaning of the word ‘Reflection’ is ‘to look back to itself’. This is
exactly what is meant by the term reflection in programming world. Reflection is an
ability of application to look into the structure of itself. Using the reflection technology,
we can retrieve the information about the contents of an assembly (constituting
classes and interfaces).

Similarly we can drill down to get the members of these types like fields, methods,
and properties. Not only this, but we can also instantiate these types and invoke the
methods on these. We can even prepare, compile, and load assemblies at runtime!!!

===== Author’s Note: ===== The concept of reflection in .Net (C# & VB.Net) is
similar to that in Java. The standard C++ does not support the reflection but there are
a number of third party libraries available that make reflection possible in C++

Reflection in .Net
The System.Reflection is the root namespace that contains classes to implement the
reflection. The Assembly class is the one which is used to represent the assembly
in .Net environment. A simple program that loads the assembly and prints the names
of the types that it contains is presented below:

using System;
using System.Reflection;
namespace ReflectionTest
{
class Test
{
[STAThread]
static void Main(string[] args)
{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("ReflectionTestAssembly.dll");
// Get the types contained in the assembly
and print their names
Type []types = myAssembly.GetTypes();
foreach(Type type in types)
{
Console.WriteLine(type.FullName);
}
}
}
}

Here we have used the static method of the Assembly class ‘LoadFrom()’ which
accepts the complete path and name of the assembly to load in string format. The
method ‘LoadFrom()’ loads an assembly into CLR and returns an instance of type
‘Assembly’ which is an abstraction of the loaded assembly. Using this instance of
type ‘Assembly’, we can do a lot of things.

In the above example, we have called the ‘GetTypes’ method of the ‘Assembly’ class
which gives an array of all the types contained in an assembly. The types are
represented by the ‘System.Type’ class. We then iterated the array and printed the
names of all the types in the assembly on Console. When the above program is run,
it produces the following output on console

ReflectionTestAssembly.MyInterface
ReflectionTestAssembly.MyClass
ReflectionTestAssembly.OurClass
Press any key to continue

Some important methods of the Assembly class are:

Method Description
Creates an instance of the specified type in the assembly and returns its
CreateInstance(string)
object
GetAssembly(Type) static This static method returns the assembly that contains the specified type.
This static method returns the assembly of the method from which the
GetCallingAssembly() static
method containing this code has been called.
This static method returns the assembly that contains this code.For
example, if we call a method in assembly B from assembly A, and the
GetExecuingAssembly() static method in assembly B contains both GetCallingAssembly() and
GetExecutingAssembly() then, GetCallingAssembly() will return
Assembly A while GetExecutingAssembly() will return Assembly B
GetModule(string) Returns the specified module that is part of this assembly
GetModules() Returns an array of all the modules of this assembly
Returns an array of all the assemblies referenced by this assembly. The
GetReferencedAssemblies()
type of array is AssemblyName
Load(AssemblyName) overloaded This static method loads an assembly into CLR provided its
static AssemblyName
LoadFrom(string) static This static method load an assembly into CLR from the specified file

Similarly, some important properties and methods of the Type class are presented in
the following table

Property Description
Assembly Returns the assembly of this type
Namespace Returns the namespace of this type
Attriutes Returns the attributes associated with this type
BaseType Returns the direct base class of the type
FullName Returns the fully qualified name of the type including namespace
IsClass Returns a Boolean value representing whether a type is a class or not
IsInterface Returns a Boolean value representing whether a type is an interface or not
IsEnum Returns a Boolean value representing whether a type is an enumeration or not
IsCOMObject Returns a Boolean value representing whether a type is a COM object or not
IsAbstract Returns a Boolean value representing whether a type is an abstract class or not
Returns a Boolean value representing whether a type is referenced type or not (i.e., passed
IsByRef
by reference)
Returns a Boolean value representing whether a type is value type or not (i.e., passed by
IsValueType
value)
IsPublic Returns a Boolean value representing whether a type is public or not
IsSealed Returns a Boolean value representing whether a type is sealed (can not be inherited) or not
Returns a Boolean value representing whether a type is serializable (can be passed to a
IsSerializable
stream) or not

And then some of the important methods of Type class are:

Method Description
GetInterfaces() Returns all the interfaces implemented or inherited by the type
Returns Boolean representing whether this type is derived from
IsSubclassOf(Type)
the type supplied in the parameter
GetNestedTypes() Returns all the types nested in this type
Returns an object of type ConstructorInfo representing the
GetConstructor(Type[])overloade
constructor of the type which takes the parameter types matching
d the supplied types
Returns an array of ConstructorInfo object representing the
GetConstructors()
constructors of the type.
Returns an array of MemberInfo object representing the members
GetMembers()
(fields, properties, methods) of this type
Returns an array of FieldInfo object representing the fields of this
GetFields()
type
Returns an array of PropertyInfo object representing the properties
GetProperties()
of this type
Returns an array of MethodInfo object representing the methods of
GetMethods()
this type
Returns an array of EventInfo object representing the events of
GetEvents()
this type
Invoke a member (constructor, field, property and method) on the
InvokeMember()
specified object type represented by this instance
Returns a boolean representing whether the current type is derived
IsInstanceOfType()
from the specified type or not

Now as we have seen the few key methods and properties of these classes; lets see
some sample code to perform these tasks.

Exploring the hierarchy of types in an assembly


In the following sample code, we will demonstrate how we can explore the hierarchy
of types in an assembly. We will get all the types contained in an assembly, list these
types along with their parent class and implementing interfaces. The source code of
the program looks like:

using System;
using System.Reflection;
namespace ReflectionTest
{
class Test
{
[STAThread]
static void Main(string[] args)
{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("ReflectionTestAssembly.dll");
// Get the types contained in the assembly
and print their names
Type []types = myAssembly.GetTypes();
foreach(Type type in types)
{
if(type.IsInterface)
{
Console.WriteLine("\r\n" +
type.FullName + " is an interface");
}
else if(type.IsClass)
{
// Get and print the list of
its parent class and interfaces
Console.WriteLine("\r\n" +
type.FullName +
" is a class whose base class is " +
type.BaseType.FullName);
Console.WriteLine("\t It
implements the following interfaces");
foreach(Type interfaceType in
type.GetInterfaces())
{
Console.WriteLine("\t\t
{0}", interfaceType.FullName);
}
}
}
Console.ReadLine();
}
}
}
Here we got the list of types in the assembly just as we did in the previous example.
We iterated through the types, checked whether it is an interface or a class using the
IsInterface and IsClass properties of the Type class

if(type.IsInterface)
{
...
}
else if(type.IsClass)
{
...
}
If the type is a class, we retrieved the name of its immediate parent class. Since all
classes in .Net are implicitly inherited from the Object class and no class can have
more than one immediate parent class, hence we are sure that the property
BaseType will return exactly one type instance.
Console.WriteLine("\r\n" + type.FullName + " is a class whose
base class is "
+ type.BaseType.FullName);

On the contrary, a class may or may not implement interfaces, so we iterated through
the list of implemented interfaces (if any) using the GetInterfaces() method which
returns an array of Type

foreach(Type interfaceType in type.GetInterfaces())


{
...
}

The complete source code of the above example can be downloaded from here

Exploring the contents of types


Now when we have learnt how to explore the contents of assembly, lets learn how to
get the contents of types. The following sample will get the list of members (fields,
properties and methods) of a class ‘MyClass’ which is defined in the assembly
‘ReflectionTestAssembly’ as

using System;
using System.Reflection;
namespace ReflectionTestAssembly
{
public interface MyInterface
{
void Fun(int iParam);
}
public class MyClass : MyInterface
{
private int number;
public readonly double PI = 3.14;
public MyClass()
{
Console.WriteLine("MyClass instantiated");
number = 6;
}
public int Number
{
get { return number; }
set { number = value; }
}
public int GenerateRandom()
{
Random r = new Random();
return r.Next();
}
public void Fun(int iParam)
{
Console.WriteLine("The parameter supplied
is fortunately {0}", iParam);
}
public void SayGreeting()
{
Console.WriteLine("Hello World!");
}
}
}

The following code loads the assembly containing MyClass dynamically and
investigates its members and their types (fields, properties, constructor, methods)

using System;
using System.Reflection;
namespace ReflectionTest
{
class Test
{
[STAThread]
static void Main(string[] args)
{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("ReflectionTestAssembly.dll");
// Get the Type object for MyClass
Type myClassType =
myAssembly.GetType("ReflectionTestAssembly.MyClass");

// Print each member information


foreach(MemberInfo miObj in
myClassType.GetMembers())
{
Console.WriteLine("The member {0} is of type
{1}",
miObj.Name.PadRight(15), miObj.MemberType.ToString());
}
Console.ReadLine();
}
}
}

Here we have called the GetMembers() method of the Type instance which returns
an array of type MemberInfo that represents a member of a type

foreach(MemberInfo miObj in myClassType.GetMembers())


{
...

Then for each member, we printed its type using the MemberType property which
returns an enumeration of type MemberTypes. When we executed the above code,
we got the following output.
The member PI is of type Field
The member Fun is of type Method
The member GetHashCode is of type Method
The member Equals is of type Method
The member ToString is of type Method
The member get_Number is of type Method
The member set_Number is of type Method
The member GenerateRandom is of type Method
The member SayGreeting is of type Method
The member GetType is of type Method
The member .ctor is of type Constructor
The member Number is of type Property

Lets have a careful look at the above output. It does not contain private field
‘number’. It also points out to some internals of CLR; the constructor is represented
by .ctor and the properties are expanded to get and set methods. Also note that it
also contains the members inherited from the Object class like GetType(), Equals(),
GetHashCode().

The complete source code of the above sample can be downloaded from here

Exploring the members of a type with specialized containers


In the previous example, we retrieved all the members in the generalized
MemberInfo objects. Now lets do the same with the specialized member type classes
like FieldInfo, PropertyInfo, MethodInfo and so on. Using these objects, we can drill
down more deeply into the members of a type. For example, with the MethodInfo
object, we can get the parameter list, parameter and return type of the type.

Consider the first sample, where we have used the FieldInfo object to retrieve
information about the fields of our type.

static void Main(string[] args)


{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("ReflectionTestAssembly.dll");
// Get the Type object for MyClass
Type myClassType =
myAssembly.GetType("ReflectionTestAssembly.MyClass");

// Get Fields and print their info


foreach(FieldInfo fiObj in myClassType.GetFields())
{
Console.WriteLine("Name of field: {0}",
fiObj.Name.ToString());
Console.WriteLine("Attributes: {0}",
fiObj.Attributes.ToString());
Console.WriteLine("Containing (declaring type): {0}",
fiObj.DeclaringType.ToString());
Console.WriteLine("Field data type: {0}",
fiObj.FieldType.ToString());
}
Console.ReadLine();
}

When we run the above code, it gives us the following output.


Name of field: PI
Attributes: Public, InitOnly
Containing (declaring type): ReflectionTestAssembly.MyClass
Field data type: System.Double

Note that it only displays the information of public members and not the private
members. Also, not that the data type is not language specific (C# int or VB.Net
Integer) but the MSIL data type (System.Double).

The complete source code of the above sample can be downloaded from here

Similarly, we can use the PropertyInfo and MethodInfo objects to get more
information about properties and methods respectively. Following sample code
demonstrates their use:

static void Main(string[] args)


{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("ReflectionTestAssembly.dll");
// Get the Type object for MyClass
Type myClassType =
myAssembly.GetType("ReflectionTestAssembly.MyClass");
// Get info about property
PropertyInfo piObj = myClassType.GetProperty("Number");
Console.WriteLine("Name of Property: {0}",
piObj.Name.ToString());
Console.WriteLine("Is Readable: {0}", piObj.CanRead);
Console.WriteLine("Is Modifiable: {0}",
piObj.CanWrite);
// Get methods and print their info
foreach(MethodInfo miObj in myClassType.GetMethods())
{
Console.WriteLine("\r\nName of Method: {0}",
miObj.Name.ToString());
Console.WriteLine("Return type: {0}",
miObj.ReturnType.ToString());
Console.WriteLine("Signature: {0}",
miObj.ToString());
}
Console.ReadLine();
}

The sample output looks like


Name of Property: Number
Is Readable: True
Is Modifiable: True
Name of Method: Fun
Return type: System.Void
Signature: Void Fun(Int32)
Name of Method: GetHashCode
Return type: System.Int32
Signature: Int32 GetHashCode()
Name of Method: Equals
Return type: System.Boolean
Signature: Boolean Equals(System.Object)
Name of Method: ToString
Return type: System.String
Signature: System.String ToString()
Name of Method: get_Number
Return type: System.Int32
Signature: Int32 get_Number()
...

The complete source code of the above sample can be downloaded from here

Consider the output generated by the code. It includes all the public or protected
methods which are either declared in the class or derived from the parent class; in
this case the System.Object class (as each class in .Net is derived implicitly from
System.Object class). Also, note that for each property, compiler generates
corresponding get_XXX and set_XXX methods where XXX is the name of the
property.

The MethodInfo class also contains other useful properties like IsAbstract,
IsConstructor, IsFinal, IsPrivate, IsPublic, IsStatic and IsVirtual. Another very
important method of the MethodInfo class is GetParameters() which returns an array
of ParameterInfo using which you can get information about the parameters of a
method. You can use ParameterInfo object just as we have used FieldInfo,
PropertyInfo, and MethodInfo objects.

Instantiating Types using Reflection


Until now, we have only explored the contents of types and their related information.
Now we will see how we can instantiate (make an object of) type and how we can
invoke members (fields, properties and methods) of type with reflection technique.
This is the first time, in this lesson, you will get an idea of how useful the technique of
reflection is!
In the following code, an object of MyClass has been created using the dynamically
loaded assembly.

static void Main(string[] args)


{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("ReflectionTestAssembly.dll");
MyClass myObj = (MyClass) myAssembly.CreateInstance
("ReflectionTestAssembly.MyClass");
myObj.SayGreeting();
Console.ReadLine();
}

Here, we used the object of Assembly class to create an instance of MyClass. Note
that the name of class here is given in the form of string. Hence, the compiler does
not know at compile time which object will be created at runtime. This is the reason
why it is another form of Polymorphism. Instead of hard coding the name of class, we
can also take input from user and use the variable name in the CreateInstance()
method. When we run the above code, we got the following output:
MyClass instantiated
Hello World!

The complete source code of the above sample can be downloaded from here

The type (MyClass) considered in the above sample did not contain any
parameterized constructor. Suppose if the constructor of the type MyClass is

public MyClass(int number)


{
Console.WriteLine("MyClass instantiated");
this.number = number;
}

Then we would use the CreateInstance() by supplying the required arguments

MyClass myObj = (MyClass) myAssembly.CreateInstance(


"ReflectionTestAssembly.MyClass",
false, BindingFlags.Default, null,
new object[] {5}, null, null);

The important thing to note here is that we have supplied an array of type
System.Object to the CreateInstance(). The elements in this array will be used as
parameters to call the constructor. Since, here we have only supplied an integer type
array of size 1; therefore, at runtime, the CLR will search for a constructor in type
MyClass which takes 1 integer argument and instantiate the type using this
constructor.

Invoking Members of Type with Reflection


As a last topic of this article, we will see how we can invoke members (fields,
properties, methods) of a type dynamically at runtime using reflection. We use the
InvokeMember() method of the Type class to get/set values from/to fields or
properties and to invoke methods. But what is different in invoking members with
InvokeMember() or by simply using the object’s reference? The basic difference is
that the compiler does not know which method (or object member) will be called at
runtime; as the name of the member is supplied in the form of string which you can
always change at runtime. Hence, the use of InvokeMember() provides the highest
degree of polymorphism and dynamic invocation.

So lets see how we can use this. When we call the InvokeMember(), we supply the
member name in string format, specify member type from
System.Reflection.BindingPolicy enumeration, target object to be used for invocation,
and the array of parameters that might be needed. The method InvokeMember()
returns the value of field, property or result of method to be called. The following
example demonstrates how we can use the InovkeMember() method to invoke fields,
properties and methods.

static void Main(string[] args)


{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("ReflectionTestAssembly.dll");
// Instantiate object
MyClass myObj = (MyClass) myAssembly.CreateInstance(
"ReflectionTestAssembly.MyClass",
false, BindingFlags.Default, null,
new object[] {5}, null, null);
// Get the Type object for this class
Type myClassType =
myAssembly.GetType("ReflectionTestAssembly.MyClass");
// Get the field value
double piValue = (double) myClassType.InvokeMember("PI",
BindingFlags.GetField, null, myObj, null);
Console.WriteLine("PI = {0}", piValue);
// Set the property
myClassType.InvokeMember("Number",
BindingFlags.SetProperty, null,
myObj, new object[] { 47 });
// Get the property value
int numValue = (int) myClassType.InvokeMember("Number",
BindingFlags.GetProperty, null, myObj,
null);
Console.WriteLine("Number = {0}", numValue);
// Invoke a parameterless method that returns nothing
myClassType.InvokeMember("SayGreeting",
BindingFlags.InvokeMethod,
null, myObj, null);
// Inovoke a method that takes an integer type parameter
and returns nothing
myClassType.InvokeMember("Fun", BindingFlags.InvokeMethod,
null, myObj,
new object[] {4});
// Invoke a parameterless method that returns an integer
type value
int rndNumber = (int)
myClassType.InvokeMember("GenerateRandom",
BindingFlags.InvokeMethod, null, myObj, null);
Console.WriteLine("Random Number = {0}", rndNumber);

Console.ReadLine();
}

An important thing to note that when we do not have any parameter to pass to some
method or getting field or property value, we pass a null value in place of parameter
array.

Polymorphism (Dynamic Invocation) through Reflection


We have discussed in C# School (or VB.Net School), polymorphism is the most
powerful concept and tool in object oriented programming. Reflection and its dynamic
member invocation allow us to achieve the highest level of polymorphism. Here we
can write code to invoke members which neither we nor compiler knows at compile
time. Consider the following code for traditional polymorphism

class A
{
public virtual void Fun() { ... }
}
class B : A
{
public override void Fun() { ... }
}
class Test
{
public static void Main()
{
A obj;
int i = new Random().Next(1);
if(i == 0)
obj = new A();
else
obj = new B();
obj.Fun();
}
}
Now neither we nor compiler knows which class’ Fun() method will be called at
runtime, but we do know that the Fun() method will be called. That is, we know the
signature of the method to be called but we don’t know which class’ object will be
used. Now lets see the following code

public class A
{
void Fun() {}
string Do(int p) { }
}
public class Test
{
public static void Main()
{
A myObj = new A();
Type myClassType = myObj.GetType();
string methodName = "";
object parameterArray = null;
int i = new Random().Next(1);
if(i == 0)
{
methodName = "Fun";
}
else
{
methodName = "Do";
parameterArray = new object [] {5};
}
myClassType.InvokeMember(methodName,
BindingFlags.InvokeMethod,
null, myObj, parameterArray);
}
}

Now neither we nor compiler knows which method will be called at runtime. We even
do not know what will be method signature that will be called as opposite to
traditional dynamism
Reflection in .Net – Develop & Use Dynamically
Pluggable Components (Part II)
In the previous part, we investigated how we can get the details of an assembly and
its containing types dynamically using the .Net Reflection technology. We also saw
that we can even instantiates the types dynamically and invoke their members. In this
article, we will go further and see how we can construct types and generate, and
execute MSIL (Microsoft Intermediate Language) code at runtime using what is
called the ‘Reflection Emit’. Later, we will go on to see how we can develop and use
dynamically pluggable components using reflection.

Dynamic Code Generation in .Net


Dynamic code generation means your code (application) generating code at runtime
based on some user selected option or activity. You might have seen a number of
programs doing similar things. For example, programs that generate database
classes for your database, database tools generating database creation scripts,
modeling software generating C#, Java, VB.Net classes from UML diagrams, Visual
Studio.Net WinForm wizard that generates code as you drag and drop controls on
your form, etc.

There are basically two methods in .Net to generate dynamic code through your
program. One is to use CodeDom library while other is to use Reflection Emit library.
The System.CodeDom library is used to generate the standard CLS (Common
Language Specification) compliant code that can be emitted in any of .Net
languages. On the other hand, the System.Reflection.Emit library is used to generate
the MSIL (Micrsoft Intermediate Language) code. With this language (compiler)
specific code, you can write any MSIL instruction and can even go for unsafe code.
While CodeDom is relatively easier to use, the reflection emit gives you more power
to directly emit in MSIL code. For the sake of demonstration and relevance to topic,
we will discuss Reflection Emit method in this lesson

Reflection Emit
Dot Net Reflection Emit allows us to construct assemblies, modules, types at runtime
and define code inside these types. We can also instantiate these types, invoke their
members and save the assembly we generated using Reflection Emit in some file.
How does it all work? Well, The System.Reflection.Emit namespace contains classes
to generate assembly, module, types and MSIL code. The general steps followed
are:

 Build assembly with the AssemblyBuilder class


 Build module with the ModuleBuilder class
 Build types with the TypeBuilder class
 Build fields, properties and methods in the type with FieldBuilder,
PropertyBuilder and MethodBuilder classes respectively
o Set appropriate flags like access modifiers (public, private, etc), static
using FieldAttributes, PropertyAttributes and MethodAttributes
enumeration
o Specify the data type of members and in case of method; its signature.
 Include IL (Intermediate Language) code in the methods using the
ILGenerator class.
o Include IL OpCodes (IL instructions) using the ILGenerator.Emit()
method which accepts OpCode type that can be selected with the
OpCodes enumeration. The OpCodes enumeration contains all the IL
op codes.
 If your assembly is executable (contains Main() method), set the entry point
using AssemblyBuilder class SetEntryPoint()
 Save your assembly in file with AssemblyBuilder class Save() method

Isn’t it all simple, straight forward and to the point? This is the essence of dot net.

Reflection Emit – Hello World Sample


To demonstrate the reflection emit, we will use the famous Hello World in reflection
emit style. It is a very simple and good source code by Joel Pobar which he wrote at
his weblog at

http://blogs.msdn.com/joelpob/archive/2004/01/21/61411.aspx
The complete source code is here

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace ReflectionEmitTest
{
class Test
{
[STAThread]
static void Main(string[] args)
{
// create a dynamic assembly and module
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "HelloWorld";
AssemblyBuilder assemblyBuilder =
Thread.GetDomain().DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder module;
module =
assemblyBuilder.DefineDynamicModule("HelloWorld.exe");

// create a new type to hold our Main method


TypeBuilder typeBuilder =
module.DefineType("HelloWorldType",
TypeAttributes.Public | TypeAttributes.Class);

// create the Main(string[] args) method


MethodBuilder methodbuilder =
typeBuilder.DefineMethod("Main",
MethodAttributes.Static | MethodAttributes.Public,
typeof(void), new Type[] { typeof(string[]) });

// generate the IL for the Main method


ILGenerator ilGenerator =
methodbuilder.GetILGenerator();
ilGenerator.EmitWriteLine("hello, world");
ilGenerator.Emit(OpCodes.Ret);

// bake it
Type helloWorldType = typeBuilder.CreateType();

// run it
helloWorldType.GetMethod("Main").Invoke(null, new
string[] {null});

// set the entry point for the application and save it


assemblyBuilder.SetEntryPoint(methodbuilder,

PEFileKinds.ConsoleApplication);
assemblyBuilder.Save("HelloWorld.exe");
Console.ReadLine();
}
}
}

The program generates an executable assembly with Main() method. In Main()


method, it simply prints ‘hello, world’ on the console and the program terminates. The
program also invokes the Main() method of the newly created type while it is still in
memory and not saved to the disk.

First of all, we created the name for our new assembly using the AssemblyName
class

AssemblyName assemblyName = new AssemblyName();


assemblyName.Name = "HelloWorld";

Then, we created an object of AssemblyBuilder class. For this we used the


DefineDynamicAssembly() method of the current application domain class
(AppDomain). We got the current app domain using the Thread class.

AssemblyBuilder assemblyBuilder =
Thread.GetDomain().DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.RunAndSave);

While calling the DefineDynamicAssembly() method, we passed it the assembly


name and specified the access level to tell the CLR which action we intend to
perform while generating this assembly. Here we specified that we want to run types
inside this assembly in this program and also we want to save this assembly into the
disk. AssemblyBuilderAccess enumeration members are Run, Save, and
RunAndSave.

Once we have created a new assembly in memory, we defined a (default) module


inside our assembly

ModuleBuilder module =
assemblyBuilder.DefineDynamicModule("HelloWorld.exe");

In this newly created module, we defined a type to hold our Main() method

TypeBuilder typeBuilder = module.DefineType("HelloWorldType",


TypeAttributes.Public | TypeAttributes.Class);

We used ModuleBuilder class DefineType() method whose arguments include the


type name, and TypeAttributes. With TypeAttributes, we specified that the new type
is a class and it’s a public class. Similarly, we can define an interface, abstract class
and sub-class (child class or the class inheriting some other class).

We then defined a method in our type using TypeBuilder class DefineMethod()


method.

MethodBuilder methodbuilder = typeBuilder.DefineMethod("Main",


MethodAttributes.Static | MethodAttributes.Public,
typeof(void), new Type[] { typeof(string[]) });

Here we specified the name of method, its attributes (static and public), return type
and the list of arguments for this method using an array of type System.Type

Now when we have added a method in our type, we need to add some IL code in the
method. We use ILGenerator class to define this IL code

ILGenerator ilGenerator = methodbuilder.GetILGenerator();


ilGenerator.EmitWriteLine("hello, world");
ilGenerator.Emit(OpCodes.Ret);

Here we first used EmitWriteLine() method of the ILGenerator class which prints
some text on the console (similar to System.Console.WriteLine() method). Note that
the EmitWriteLine() will not print the ‘hello, world’ on the console when we run the
application. It will simply add the IL code similar to System.Console.WriteLine()
method in our Main() method of newly created assembly which is still in the memory.
Since we do not want to do any other thing, we need to close our method. For this,
we use the Emit() method and specified through OpCodes enumeration that its all
and just return from the method. The Emit() method accepts IL op codes, which you
can provide using OpCodes enumeration.

Then we got the reference of our newly created type (which is still in memory) and
invoked its static Main() method to display ‘hello, world’ on console window

Type helloWorldType = typeBuilder.CreateType();


helloWorldType.GetMethod("Main").Invoke(null, new string[]
{null});

Note that since Main() is a static method, we supplied null in place of target object
(first) parameter of the Invoke() method of the MethodInfo class.

Finally, we set the entry point of our assembly as the Main() method and saved it to
the file

assemblyBuilder.SetEntryPoint(methodbuilder,
PEFileKinds.ConsoleApplication);
assemblyBuilder.Save("HelloWorld.exe");

That’s all it takes to get started with the Reflection Emit technology of Microsoft .Net!!!
Author’s Note: We stop here and do not go into the details of Reflection Emit as it
requires the sound understanding of MSIL and compiler construction. We would,
however, encourage compiler construction students to get into more details of this
topic.

Cross Language Dynamic Type Loading and Usage with Reflection


All the .Net based compilers emit the same standard MSIL; hence we can use
reflection to load assemblies built with other compilers, instantiate types inside
assembly and invoke the members of these types. To demonstrate, lets make an
assembly in VB.Net. We created a VB.Net class library project named
‘VBDotNetAssembly’ and defined a class named ‘VBClass’ as:

Public Class VBClass


Public Sub New()
Console.WriteLine("New object created")
End Sub
Public Sub Hello()
Console.WriteLine("Hello World")
End Sub
Public Function Sum(ByVal a As Integer, ByVal b As Integer)
As Integer
Return a + b
End Function
End Class

We built the project to get the compiled VBDotNetAssembly.dll file. Now we just
loaded the assembly and instantiate the type ‘VBClass’ and its members as we
earlier used the C# assembly.

using System;
using System.Reflection;
using VBDotNetAssembly;
namespace ReflectionTest
{
class Test
{
[STAThread]
static void Main(string[] args)
{
// Load an assembly from file
Assembly myAssembly =
Assembly.LoadFrom("VBDotNetAssembly.dll");
// Instantiate object
VBClass vbObj = (VBClass) myAssembly.CreateInstance(
"VBDotNetAssembly.VBClass",
false, BindingFlags.Default, null,
null, null, null);
// Get the Type object for this class
Type vbClassType =
myAssembly.GetType("VBDotNetAssembly.VBClass");
// Invoke a parameterless method that returns nothing
vbClassType.InvokeMember("Hello",
BindingFlags.InvokeMethod,
null, vbObj, null);
// Inovoke a method that takes two integer type
parameters and returns
//integer

int total = (int) vbClassType.InvokeMember("Sum",


BindingFlags.InvokeMethod, null,
vbObj, new object[]{4, 3});
Console.WriteLine("Total = {0}", total);
Console.ReadLine();
}
}
}
.

When we run the above program, we get the following output

New object created


Hello World
Total = 7

Hence we can see that dynamic type loading and member invocation through
reflection is not language dependent; we can load and use assemblies built with any
dot net based compiler.

Developing and Using Pluggable Components with Reflection


Now lets move to the final part of the topic where we will see how we can use
reflection to develop and use dynamically pluggable components. There are various
situations where you want your application to support dynamically pluggable
components. For example, a web server accepts a lot of services (websites) that can
be added and configured with it dynamically, in a certain game you may allow users
to download news stages or characters, in an instant messenger you may allow
users to download and add new emoticons and themes, etc. How to achieve this?

First of all, all the dynamically pluggable components must comply with the common
standard (implement interface or abstract class in OOP). These components can be
added to the application by adding there DLL files. Since, the types in the DLL files
(assembly in .Net) are to be examined, loaded and used dynamically, we need to use
.Net reflection technology for this.

To demonstrate this, lets develop a Task Scheduler which is capable of repeating


various tasks after specified interval of time. The tasks (in the form of DLL) can be
added to the scheduler (application) at any time. The task scheduler form looks like:

http://www.programmersheaven.com/articles/faraz/reflection/image001.gif

A user selects the DLL file of the task he/she wants to schedule and specify the time
interval to repeat the task. The scheduler then starts the task and repeats it after the
specified time interval.

The first step in designing the application is the standard which all the tasks should
comply with. A task can do whatever it wants, the scheduler should be able to start
the task and repeat it after regular interval. Hence, we defined an interface named
‘Schedule’ in the ‘AbstractSchedule’ assembly (a C# class library project) as:

using System;
namespace AbstractSchedule
{
public interface Schedule
{
void Start();
}
}

The ‘Schedule’ interface only contains one method ‘Start()’ which will be used the
schedule manager start and repeat the task. All the concrete tasks will implement this
method. For example, we have method a task named ‘GreetingTask’ which is a class
library project (assembly). It contains only one class ‘Greeting’ implementing the
‘Schedule’ interface.

using System;
using AbstractSchedule;
namespace GreetingTask
{
public class Greeting : Schedule
{
public void Start()
{
Console.WriteLine("Greeting Task: Hello, World again!");
}
}
}

We developed another task named ‘TimerTask’ which is also a class library project
(assembly). It also contains a class ‘Timer’ implementing the ‘Schedule’ interface.
When invoked it will simply print the current time at Console.

using System;
using AbstractSchedule;
namespace TimerTask
{
public class Timer : Schedule
{
public void Start()
{
Console.WriteLine("Timer Task: Current Time --> {0}",
DateTime.Now.TimeOfDay.ToString());
}
}
}

Now coming to the TaskManager, we developed a windows form application named


‘ScheduleManager’ which contains one form and our task manager. The task
manager contains static methods to add, stop and validate tasks. As we showed
earlier that tasks will be supplied to the application in the form of their dll files; so the
first of all the task manager should be able to validate whether the supplied dll is the
valid task. At this point, one may ask ‘how do you define the valid task?’ Well for our
application any dll that contains a class implementing the AbstractSchedule.Schedule
interface is a valid dll. Hence, the ValidateTask() looks like

public static bool ValidateTask(string fileName)


{
try
{
Assembly taskAssembly = Assembly.LoadFile(fileName);

Type taskType = null;


Type []types = taskAssembly.GetExportedTypes();
foreach(Type type in types)
{

if(type.GetInterface("AbstractSchedule.Schedule") !=
null)
{
TaskType = type;
{
}
if(taskType == null)
return false;
else
return true;
}
catch(Exception)
{
return false;
}
}

The ValidateTask() accepts the file name with path of the DLL, it attempts to load the
assembly, iterate through all of its types and check if there is any type (class) that
implements the ‘AbstractSchedule.Schedule’ interface. If finds one, it returns true
else it returns false. Also, if there is any exception in doing all this (e.g., the file path
of the dll supplied is not a valid .Net dll), it also returns false.

The next thing, the TaskManager needs to do is to start the task. The task manager
starts each task in a separate thread so that no task can block the application
processing. To manage all these thread, we have an ArrayList to hold all the threads
running

public class TaskManager


{
static ArrayList threads = new ArrayList();
...
}

Now the AddTask() method is defined as follows:

public static void AddTask(string fileName, int interval)


{
TaskThread taskTh = new TaskThread(fileName, interval);
Thread th = new Thread(new ThreadStart(taskTh.Run));
threads.Add(th);
th.Start();
}

For the repeated execution of the tasks, we have defined a class named
TaskThread. Whenever a task is required to be started, we create an object of this
TaskThread and start a new thread with the execution of TaskThread class Run()
method which repeat the execution of task after given interval of time. The class
TaskThread is defined as follows:

public class TaskThread


{
string fileName;
int interval;
public TaskThread(string fileName, int interval)
{
this.fileName = fileName;
this.interval = interval;
}
public void Run()
{
Assembly taskAssembly = Assembly.LoadFile(fileName);

Type taskType = null;


Type []types = taskAssembly.GetExportedTypes();
foreach(Type type in types)
{
if(type.GetInterface("AbstractSchedule.Schedule") !=
null)
{
taskType = type;
}
}
// Instantiate object
Schedule task = (Schedule) taskAssembly.CreateInstance(
taskType.FullName,
false, BindingFlags.Default, null,
null, null, null);
while(true)
{
task.Start();
Thread.Sleep(interval*1000);
}
}
}

Each TaskThread object contains file name and time interval to repeat the task.
When the task is started, it loads the assembly with the supplied file name, iterate
through its types to get the type implementing the ‘AbstractSchedule.Schedule’
interface. It then instantiate the type and using the ‘Schedule’ interface reference,
execute it repeatedly after regular interval of time. Note that, we expect the interval
supplied by user to be in seconds while the Thread.Sleep() method expects the
interval to be in milliseconds, hence we multiplied the interval value by 1000 to
convert it to the milliseconds.

Finally since each task is being started in different thread, we need to stop all these
threads when the application is to be closed. The StopTasks() method perform this
operation

public static void StopTasks()


{
foreach(Thread th in threads)
{
th.Abort();
}
}

Now when we have completed the background design, lets design the user interface
form for the application. Make the form look like as:

http://www.programmersheaven.com/articles/faraz/reflection/image002.gif

The ‘Select Task…’ button allows user to select the dll file for the task. The event
handler for this is:
private void btnSelectTask_Click(object sender,
System.EventArgs e)
{
openFileDialog.Filter = "DLL files (*.dll)|*.dll| EXE files
(*.exe)|*.exe" ;
DialogResult res = openFileDialog.ShowDialog();
if(res == DialogResult.OK)
{
txtTask.Text = openFileDialog.FileName;
}
}

It displays the open file dialog box to allow user select the dll file. The openFileDialog
is defined in the form as:

public class frmScheduleManager : System.Windows.Forms.Form


{
private OpenFileDialog openFileDialog = new OpenFileDialog();

When user press the ‘Add Task’ button, the task file is first validated and then added
to the currently executing tasks.

private void btnAddTask_Click(object sender, System.EventArgs


e)
{
if(TaskManager.ValidateTask(txtTask.Text))
{
TaskManager.AddTask(txtTask.Text,
int.Parse(txtInterval.Text));
lbxNowRunningTasks.Items.Add(txtTask.Text);
}
else
{
MessageBox.Show("The dll file does not contain valid
task", "Invalid Task");
}
}

Finally, since all the tasks are being started in their own threads and the threads are
never ending by themselves, we need to stop these threads when the application is
to be closed. Hence, the StopTasks() method of the TaskManager is called on the
OnClosing() event of the form

private void frmScheduleManager_Closing(object sender,


System.ComponentModel.CancelEventArgs e)
{
TaskManager.StopTasks();
}
This is all! The complete source code of the application can be downloaded by
clicking here

When the application is executed and the tasks are added, you can see the output
(repeating hello world and current time) in the Output window. If you can not find the
Output window in your Visual Studio.Net, select View->Other Windows->Output

http://www.programmersheaven.com/articles/faraz/reflection/image003.gif

So, in this lesson we saw how we can use the reflection technology to allow
components to be plugged dynamically in our applications. Reflection is indeed a
very useful technology that allows the code to reason about itself.

Reflection in framework:
Protected Friend Sub CopyState() Implements IUndoableObject.CopyState

Dim currentType As Type = Me.GetType


Dim state As New HybridDictionary()
Dim fields() As FieldInfo
Dim fieldName As String

Do
' get the list of fields in this type
fields = currentType.GetFields( _
BindingFlags.NonPublic Or _
BindingFlags.Instance Or _
BindingFlags.Public)

For Each field As FieldInfo In fields


' make sure we process only our variables
If field.DeclaringType Is currentType Then
' see if this field is marked as not undoable
If Not NotUndoableField(field) Then
' the field is undoable, so it needs to be processed
Dim value As Object = field.GetValue(Me)

If GetType(Csla.Core.IUndoableObject). _
IsAssignableFrom(field.FieldType) Then
' make sure the variable has a value
If Not value Is Nothing Then
' this is a child object, cascade the call
DirectCast(value, IUndoableObject).CopyState()
End If

Else
' this is a normal field, simply trap the value
fieldName = field.DeclaringType.Name & "!" & field.Name
state.Add(fieldName, value)

End If

End If

End If
Next

currentType = currentType.BaseType

Loop Until currentType Is GetType(UndoableBase)

' serialize the state and stack it


Using buffer As New MemoryStream
Dim formatter As New BinaryFormatter
formatter.Serialize(buffer, state)
mStateStack.Push(buffer.ToArray)
End Using
CopyStateComplete()

End Sub

You might also like