Note
Author�s intention was not to provide a complete overview of .NET reflection. This article illustrates a practical implementation of one of the common tasks that developers face every day, using Reflection.
What is Reflection?
.NET reflection is a classical example of a low-level API which can be used to solve high-level tasks. So what is it? Reflection (syn. introspection) is a subsystem that provides the code with the information about itself. Sounds a little bit complicated, and apparently, an example is the best way to grasp the idea. Suppose we�ve got class MyCar
, which provides a Start
method:
public class MyCar
{
public void Start()
{
Console.WriteLine("Started!");
}
}
MyCar car = new MyCar();
car.Start();
Now we are going to dive into introspection. We will get some type information for MyCar
:
Type myCarType = typeof(MyCar);
myCarType
now has a reference to the metadata that describes the MyCar
class. We can obtain further info about its properties, fields, methods, events and so on. You can consult MSDN or Code Project articles about reflection. What we need to know is if we can get this info.
Also, .NET allows us to get type information given a full type name:
Type myCarType = Type.GetType("Serge.ReflectionSample.MyCar", false, true);
What can we do after we�ve obtained this reference? Create a class instance, of course (an object
). In order to do this you need to get the constructor info:
if(myCarType != null)
{
ConstructorInfo ci = myCarType.GetConstructor(new Type[]{});
object myCarReflected = ci.Invoke(new object[]{});
}
Now we�ve got a reference to the newly created object of type MyCar
. What next?
Apparently, we cannot do much having a reference of type object
, but what .NET provides is enough. Nothings stops us from casting myCarReflected
to MyCar
, doesn�t it? Another solution. Suppose, MyCar
implements IVehicle
, and our application doesn�t care about the interface implementation. So we cast myCarReflected
to IVehicle
and use the interface members.
Let�s sum things up:
- We can get information about any type by its name.
- We can obtain a reference to a desired constructor.
- We can instantiate an object using this information.
- We can cast an object to one of the supported types.
Our application
A great number of developers faced the necessity to use the switch
operator to judge which class needs to be instantiated. The author, as a senior .NET developer, happened to see switch
-blocks which exceeded pages. In one of the projects the application had to parse an XML template file and produce an in-memory tree of the corresponding objects. Also, it had to provide a way to import new node types into the system without having to modify the core functionality. In this article I present a simplified solution � no separate assemblies or XML nodes. A shrewd reader might have already guessed what I am driving to. If not so, browse through the code, it�s documented enough. If so, you�re encouraged to take a look, too.
Result
Please, feel free to ask questions if necessary.