Reflection in .NET: Part 1

Preface

 
This series of articles will explain Reflection in .NET in detail, then take a deep dive into its various aspects and also cover the various classes in the System.Reflection namespace. On our path to understand Reflection, we will be covering many sample examples (demo programs that I have created) to explain the concept practically. I will be including various techniques using examples (demo programs) that the programmers can use in their applications when implementing Reflection.
 

Introduction

 
An Assembly is the minimum unit of deployment. You cannot deploy anything less than an Assembly. For the CLR, a type does not exist outside the context of an Assembly. Assemblies contain four elements (the Assembly manifest, type metadata, MSIL, and resources.). Each Assembly contains a collection of data that describes how the elements in the Assembly related to each other. For more information on Assemblies (see the bottom section, References). In our custom .NET applications, when using reflection the Type metadata information will be used.
 

Reflection

 
Reflection in .NET allows us to programmatically load Assemblies and obtain information about the types (classes, interface, and value types) defined in the Assemblies.
 
Reflection can also be used to dynamically create an instance of a type, bind the type to an existing object, or get the type information from an existing object. The .NET Framework includes System.ReflectionSystem.Type and they together form the reflection API, this API can be used to programmatically obtain information about the loaded Assembly.
 
Reflection also allows you to perform late binding,  wherein you load the Assembly, access the type, create an instance of the type, invoke the methods of the type (using the method name), all at Runtime.
 
Let's start with our first Demo.
 

Using Reflection, for Loading a .NET Framework Assembly and displaying the types

 
The following is the image of the running code, console application (see attachments for the complete code). In the following procedure, I will walk you through each line of the code.
 
Running code console application
 
Figure 1: Running code console application
 
In this console application example,  we are loading the .NET Assembly (System.Data.dll) and looping through the types contained in this Assembly at runtime using reflection.
 
First, you specify the reflection namespace using the using directive.
  1. using System.Reflection; // Using the Reflection Assembly  
Inside the Main method (entry point for most types of C# applications) define a string variable to specify the exact location (path) of the Assembly (you can specify any other .NET Assembly name with the complete path).
  1. string assemblyPath = @"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\System.Data.dll";  
On the next line, the preceding specified path would be used to load the Assembly using LoadFrom(), that accepts a string parameter (in other words the path of the Assembly).
  1. Assembly assembly = Assembly.LoadFrom(assemblyPath);  
On the next line, we display the full name (fully qualified name of the Assembly with namespace information, name, version, culture, and public key) of the Assembly that's loaded.
  1. // Get the complete name of the assembly that is loaded from the file using FullName or GetName()  
  2. Console.WriteLine("Assembly Full Name : {0}", assembly.FullName);  
In the next line using the GetTypes() method we will get all the types from the loaded Assembly in aType[].
  1. //Store the types contained in the assembly in an array  
  2. Type[] assemblyTypes = assembly.GetTypes();  
We will then use foreach to loop through the types and display the FullName property of each type on the console screen.
  1. foreach (Type t in assemblyTypes) Console.WriteLine(t.FullName);  
Console screen
 
Figure 2:
Console screen
 
We can further extend this example to display the Methods and Public Properties contained under each type for this loaded Assembly.
 
The following is the complete running code. I will walk you through the foreach loop section of the following code:
 
Complete running code
 
Figure 3: Complete running code
 
Inside the foreach loop, we define an array of MemberInfo[] and then, using the GetMembers() method of the Type class, we get all the member information.
  1. //Search for the members based on the criteria specified in the BindingsFlags   
  2. MemberInfo[] membersinfo = t.GetMembers(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);   
Note: Here I have specified the BindingsFlag, it's used for specifying the way in which reflection should do a search for the Member under each type. (In this case, the search should be only one public member and second, the member declared in the Type and not inherited from the base type and third, a search for only instance members, in other words, non-static members).
 
Not having BindingsFlag will get all the information about the members for that specific type and in most cases, we would need only specify member info, so in such cases, bindingFlags criteria would help.
  1. foreach (MemberInfo m in membersinfo) Console.WriteLine("Member type: {0}, member name: {1}.", m.MemberType, m.Name);  
We then display the member type and the member name under each Type for the loaded Assembly.
 
Loaded assembly
 
Figure 4:
Loaded Assembly
 
Learning Points: 
  1. Learn what reflection is
  2. How to load a .NET Framework Assembly using Reflection
  3. Display the types from the loaded Assembly
  4. Display the members, Properties, Fields, and Methods for each Type
  5. Use of BindingFlag
References
 
Note:
This article had been earlier published on CodeProject. Other members suggested I upload it here for C# Corner members, this is my first ever article. If encouraged with suggestions and comments, I will continue to write more and publish.


Similar Articles