What is reflection?
Reflection refers to a programming technique by which a developer can empower an assembly to inspect and modify
itself or other assemblies in the current app domain at runtime. Those
inspections enable the developer to implement late-bound functionality that is
much more dynamic than what could be achieved using other means. Reflection is
somewhat new to Microsoft development methodologies; However, Java and several
other modern languages contain functionality that is very similar. As a feature
of the .NET Framework, reflection can be taken advantage of by any
.NET compliant language such as C#, VB.NET, or J#. The sample C# project that
accompanies the downloadable version of this articleillustrates some of the
techniques introduced in this document.
How does reflection work?
Each assembly generated for the .NET Framework contains
metadata which describes the assembly and the classes or structures inside the
assembly. By using metadata, reflection can enumerate all classes, structures,
and data that an assembly contains. Once the capabilities of an assembly are
known, it is possible to modify and take advantage those capabilities.
To illustrate how reflection uses metadata, consider the
following except (Listing A) from
the sample C# project.
Listing A
C#:
private string ListProperties(object objectToInspect)
{
string returnString = “”;
//To use reflection on an object, you
// first need to get an instance
// of that object’s type.
Type objectType = objectToInspect.GetType();
//After you have the object’s type, you can get
// information on that type. In this case, we’re
// asking the type to tell us all the
// properties that it contains.
PropertyInfo[] properties =
objectType.GetProperties();
//You can then use the PropertyInfo array
// to loop through each property of the type.
foreach(PropertyInfo property in properties)
{
//The interest part of this code
// is the GetValue method. This method
// returns the value of the property.
returnString += property.Name + “: ” +
property.GetValue(objectToInspect, null) +
“\r\n”;
}
return returnString;
}
In this code segment, we are enumerating the properties that
are contained in a class. To accomplish this, reflection uses the metadata in
the assembly to return a PropertyInfo array
that contains the properties in the class. We can then loop through the PropertyInfo array and
access each property individually.
When using reflection, the process of reading metadata is
transparent to the developer. However, the fact that reflection uses the
metadata is an important point to consider.
The uses of reflection
Reflection can be used to implement a wide range of
functionality. Most serialization engines use reflection to extract data from
the objects that need to be serialized. Reflection can also be used to create
customizable application architectures through the use of plug-in modules. Many
Object Relation Modeling (ORM) solutions also take advantage of reflection to
implement dynamic mapping functionality.
While not widely publicized, one of the most interesting
uses of reflection is its ability to dramatically reduce the time required to
complete monotonous development tasks. Reflection frequently is a very good
alternative to code generation tools because reflection is completely dynamic,
which allows you to change underlying structures without having to re-generate code.
For example, many code generation tools allow you to create
data objects based on the underlying database. Reflection can be used to
dynamically extract business objects (classes) from data structures such as DataTables that
are returned from the database. Using this method, there is no need to use a
code generator to generate the code. You can simply loop through the columns in
a DataTable
and dynamically match the column names to the property names of your business
object.
Reflection can also be used to dynamically bind an object’s
properties to an array of stored procedure parameters. In combination with the downloadable
example, this binding allows you to create generic data access methods that
provide many of the benefits code generation tools offer you, with the
advantage of being totally dynamic. Reflection therefore can dramatically
decrease your code base and ease application maintenance.
Just the surface
In this article, we’ve just scratched the surface of the
things reflection can do to help developers write better code. In future
articles, I’ll build on this introductory article by presenting other uses of reflection and its capabilities in greater detail. Topics I
will cover include accessing methods and properties of a class at runtime,
extracting business objects from data structures, and creating a generic data
access tier that can be used by multiple projects.