Coding Concepts – Reflection

Coding Concepts Reflection

Reflection – What you need to know.

In computer science, reflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at runtime.[1]

So what does that mean? Reflection is a term thrown around every now and again and but do you really know what it means? Why and when it should be used, and what are its main strengths? It’s a pretty difficult concept to grasp, but it’s well worth the effort to learn as it can make certain seemingly impossible tasks possible.

Usually I run through examples in JavaScript to keep it understandable for most people, however reflection in JavaScript is not really the same as  in precompiled Object Oriented languages such as Java and C#, as it doesn’t contain classes per se, so we’ll be using examples from those today. The .Net Framework and Common Language Runtime (CLR) use reflection heavily for features such as Intellisense and other IDE features within Visual Studio as well as for serialisation so you’ll probably be using reflection without even knowing about it.

Let’s take a look at this example in C#.

// Using GetType to obtain type information:  
int i = 42;  
System.Type type = i.GetType();  
System.Console.WriteLine(type);

As you would have guessed the output in the console is:

System.Int32

So this static method GetType uses reflection to obtain the type of the variable! Obviously when writing the code we know that “i” is an Integer but the runtime doesn’t have this knowledge to hand, so it must search within itself to figure it out! Most people will have used GetType in the past, but some may have not known how it obtains the type!

Let’s look at the main uses of Reflection and answer some of the questions raised above, I’ll try and keep it easy to follow.

When to use reflection and why!

  • Traditionally used to load modules/classes from assembly and create an instance of them, at runtime.
  • For getting an Object’s Public Attributes.
  • During testing, creating mock objects during runtime initialisation.
  • To create Generic libraries to handle different formats without redeployments, sometimes referred to, or using Implicit Late Binding.
  • When building new types at runtime.
  • For examining and instantiating types in an assembly.
  • The ability to change the value of a field marked private in a 3rd party library.

The ability to inspect the code in the system and see object types is not reflection, but rather Type Introspection. Reflection is then the ability to make modifications at runtime by making use of introspection. The distinction is necessary here as some languages support introspection, but do not support reflection. One such example is C++

So as you can see it’s mainly about classes, looking at them, changing them, instantiating them, but all at runtime rather than compile time!

Compile Time Vs Runtime

The best way I can explain the difference between the two is by looking at your running shoes!

Compile time is like doing up your shoe laces and checking them before you go out for a run. Whatever you do to your shoes will be saved and kept. This will give you an insight whether anything is wrong with them, and what they contain and can do.

Runtime is when you’re already out on the road! Your shoes have already been prepared for you, you can’t usually change those shoes or retie those laces unless you stop, but you can see what the shoes are capable of, and use any existing features that these shoes have available! You could switch shoes by jumping into a new set, but this requires the new set of shoes to be already created too and available to you on the run.

In object-oriented programming languages, reflection allows inspection of classes, interfaces, fields and methods at runtime without knowing the names of the interfaces, fields, methods at compile time. It also allows instantiation of new objects and invocation of methods.

So above we had an example of using reflection on an object and getting the object attributes, now lets looks at using reflection to get info from a Type, and how we’d find and load new assemblies during runtime.

		// Using Reflection to get information from an Assembly:  
		System.Reflection.Assembly integerTypeAssembly = typeof(System.Int32).Assembly;  
		System.Type integerType = typeof(System.Int32);
		
		System.Console.WriteLine(integerTypeAssembly); // mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
		System.Console.WriteLine(integerType.ToString()); // System.Int32
		
		//Use this typeString to refind the type
		Type calcType = integerTypeAssembly.GetType(integerType.ToString());
		System.Console.WriteLine(calcType); // System.Int32
		
		// We can then Create a new Instance of whatever this type may be, and call it's methods.
		object integerInstance = Activator.CreateInstance(calcType); 
		// In this case it's just a boring Integer, and we can see it's been initialised to it's default of 0..
		System.Console.WriteLine(integerInstance.ToString());

We can see the nuanced difference of looking at a variable that was set during compilation, and querying the library itself, and the different ways we can use these two types of reflection to make changes to the system during runtime.

A Real World Example

A useful real world example of using reflection would be switching between assemblies based on a value stored in a database or other static resource. For example: you have “GoogleSearchService” and “BingSearchService” configured in your system. Usually you would hard code/inject one of these services as the one to be used.

But say for instance you had a “LoadSearchServiceAssemblyFromResource()” method that retrieved the service from your database which would then be used at runtime.

If this service was to go down, become obsolete, or your contract was to be terminated, rather than having to redeploy your system using “BingSearchService”, you would simply update your database/storage field pointing to your other assembly(“BingSearchServiceAssembly”).

The next time your Search Service was called, it would switch dynamically at runtime to your new Service. This for me is the  major benefit of reflection and why it can or should be used. As each service is a dll you can call them directly using reflection using a format such as this.

//This will load the dll from a static resource such as a DB or File
Assembly searchAssembly = LoadSearchServiceAssemblyFromResource();
// Now we need to find the class in the assembly, this in this instance is simply called "Search"
Type searchType = searchAssembly.GetType(searchAssembly.GetName().Name + "Search");

// If we have found the class
if (searchType != null)
{
	object searchResult = null;
	dynamic classInstance = Activator.CreateInstance(searchType);
	// DoSearch is a method that is declared on both SearchService Classes!
	var searchResult = instance.DoSearch();
}

You may not always have the scenario to use it, but knowing when and why you should is invaluable.

There’s load more to Reflection that hasn’t been covered here. So have a look at the additional reading if you want to read more on the topic.


Additional Reading

Microsoft Concept Docs – Reflection

Type Introspection and Reflection

Microsoft – Reflections and CodeDom

Microsoft Reflection – Dynamically Loading and Using Types

StackOverflow – What is reflection and why is it useful

 

Leave a Reply

Your email address will not be published. Required fields are marked *