Preface
In this series of articles, we would be discussing in detail about - Reflection in .NET, and then take a deep dive into different aspects of Reflection in .NET and also cover the various classes in System.Reflection
namespace. On our path to understanding Reflection, we would be covering a lot of sample examples (demo programs which I have created) to explain the concept practically. I will be including various techniques using examples (demo programs) which the programmers can use in their applications while 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 contains 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 relate to each other. For more information on Assemblies, see bottom section – References. In our custom .NET applications, while using Reflection, the Type metadata information will be used.
What is Reflection?
Reflection in .NET allows us to programmatically load the assemblies and obtain information about the types (classes, interface and value types) defined in the assemblies.
Reflection can also be used to dynamically create instance of a type, bind the type to an existing object, or get the type information from and existing object. The .NET framework includes System.Reflection
and the System.Type
and they together form the reflection API, this API can be used to programmatically obtain information of 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
Below is the complete running code (console application). In the steps below, I will walk you through each line of the code.
using System;
using System.Reflection;
namespace Reflection_Client_Sample
{
class Program
{
static void Main(string[] args)
{
string assemblyPath = @"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\System.Data.dll";
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Console.WriteLine("Assembly Full Name : {0}", assembly.FullName);
Type[] assemblyTypes = assembly.GetTypes();
foreach (Type t in assemblyTypes)
{
Console.WriteLine(t.FullName);
}
Console.Read();
}
}
}
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 the reflection.
First, you specify the reflection namespace using the using
directive.
using System.Reflection;
Inside the Main
method (entry point for C# console application), define a string
variable to specify the exact location (path) of the assembly. (You can specify any other .NET assembly name with complete path).
string assemblyPath = @"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\System.Data.dll";
On the next line, the above specified path would be used to load the assembly using LoadFrom()
, which accepts a string
parameter (i.e., path of the assembly).
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.
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 a Type[]
.
Type[] assemblyTypes = assembly.GetTypes();
We will then use foreach
to loop through the types and display the FullName of each type on the console screen.
foreach (Type t in assemblyTypes)
Console.WriteLine(t.FullName);
We can further extend this example, to display the methods and public
properties contained under each type for this loaded assembly.
Below is the complete running code. I will walk you through foreach
loop section of the code.
using System;
using System.Reflection;
namespace Reflection_Client_Sample
{
class Program
{
static void Main(string[] args)
{
string assemblyPath = @"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\System.Data.dll";
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Console.WriteLine("Assembly Full Name : {0}", assembly.FullName);
Type[] assemblyTypes = assembly.GetTypes();
foreach (Type t in assemblyTypes)
{
Console.WriteLine(t.FullName);
MemberInfo[] membersinfo = t.GetMembers
(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
foreach (MemberInfo m in membersinfo)
Console.WriteLine("Member type: {0}, member name: {1}.", m.MemberType, m.Name);
}
Console.Read();
}
}
}
Inside the foreach
loop, we define an array of MemberInfo[]
and then using the GetMembers()
method of Type
class, we get all the member information.
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 search for the Member
under each type (in this case, the search should be one - only public
member, second – members which are declared in the Type
and not inherited from base type and the third search for only instance members, i.e., non-static members).
Not having BindingsFlag
will get all the information about the members for that particular type and in most cases, we would need only specify member information, so in such cases bindingFlags
criteria would help.
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.
Points of Interest
- Learn What Reflection is?
- How to load a .NET framework assembly using Reflection
- Display the Types from the loaded assembly
- Display the members - Properties, Fields and Methods under each Type
- Use of
BindingFlags
References
In the next article, we will load a custom .NET application Class library DLL and find the type and member information. We will discuss in detail the System.Type
.