Using Reflection to Migrate code to C#

As with many software companies that have been around since before the browser wars, web 2.0 and our current age of new MVC frameworks being launched every couple of days, we have “legacy” code. Lots of it. The vast majority of our legacy code is written in a language called Delphi, and we still perform tweaks and maintenance on it every day.

10 years ago when we started producing new systems using the Microsoft .Net Framework. These newer systems are written in C# and take advantage of all the benefits a modern language has to offer with the added ability of having access to our 30 years so of legacy code compiled as .Net DLLs. The down side of this is the added baggage that Delphi.Net comes with. Even tiny little applications that we want to use a snippet of legacy code with required 20 or so additional DLLs to be dragged in so that it works.

To remove this bloat from our smaller applications, we need to duplicate some of our legacy library directly in CSharp. The catch being, we need to keep the two libraries in sync. We therefore need to automate the library generations as much as possible, allowing us to regenerate our classes whenever they are changed in our Delphi library. This is where the Reflection features of the .Net Framework become our new best friend.

Reflection in .Net provides us with libraries run-time objects that describe the classes that are referenced at run time.

The simplest example of reflection is the typeof function:

Type typeString = typeof(System.String);

The returned Type object will expose the constructors, properties, methods and fields of the class String. For example:

//Get the constructors of type String
ConstructorInfo[] constructors = typeString.GetConstructors();
foreach (ConstructorInfo constr in constructors)
    Console.WriteLine (constr);
//Get the properties of type String
PropertyInfo[] properties = typeString.GetProperties();
foreach (PropertyInfo prop in properties)
    Console.WriteLine (prop);
//Get the fields of type String
FieldInfo[] fields = typeString.GetFields();
foreach (FieldInfo field in fields)
    Console.WriteLine (field);
//Get the methods of type String
MethodInfo[] methods = typeString.GetMethods();
foreach (MethodInfo meth in methods)
    Console.WriteLine (meth);

In each case above, we can investigate these “info” objects to discover more about that aspect of the class. For instance, using a PropertyInfo, we can determine it’s name, return type, it’s get and set methods, whether it is public, private, static, read only etc. We can also use an instance of the class in conjunction with an info object to execute a function, get a value of a property etc.

Performing this analysis on our Delphi.Net library in conjunction with some code to create plain text files is allowing us to generate our own CSharp versions of many of our legacy Delphi objects. Sometimes we are generating entire classes, especially when there is minimal business logic with in the class, and sometimes just interfaces to be used to manually implement the CSharp version. It’s proving invaluable to us, and giving us a real opportunity to migrate our library without double maintenance.

I will post a more detailed example of digging in to types using reflection soon, but have a play and have a think about how else you could use reflection yourself.