How could Reflection not lead to code smells?

Reflection is most commonly used to circumvent the static type system, however it also has some interesting use cases:

Let's write an ORM!

If you're familiar with NHibernate or most other ORMs, you write classes which map to tables in your database, something like this:

// used to hook into the ORMs innards
public class ActiveRecordBase
{
    public void Save();
}

public class User : ActiveRecordBase
{
    public int ID { get; set; }
    public string UserName { get; set; }
    // ...   
}

How do you think the Save() method is written? Well, in most ORMs, the Save method doesn't know what fields are in derived classes, but it can access them using reflection.

Its wholly possible to have the same functionality in a type-safe manner, simply by requiring a user to override a method to copy fields into a datarow object, but that would result in lots of boilerplate code and bloat.

Stubs!

Rhino Mocks is a mocking framework. You pass an interface type into a method, and behind the scenes the framework will dynamically construct and instantiate a mock object implementing the interface.

Sure, a programmer could write the boilerplate code for the mock object by hand, but why would she want to if the framework will do it for her?

Metadata!

We can decorate methods with attributes (metadata), which can serve a variety of purposes:

[FilePermission(Context.AllAccess)]    // writes things to a file
[Logging(LogMethod.None)]              // logger doesn't log this method
[MethodAccessSecurity(Role="Admin")]   // user must be in "Admin" group to invoke method
[Validation(ValidationType.NotNull, "reportName")] // throws exception if reportName is null
public void RunDailyReports(string reportName) { ... }

You need to reflect over the method to inspect the attributes. Most AOP frameworks for .NET use attributes for policy injection.

Sure, you can write the same sort of code inline, but this style is more declarative.

Let's make a dependency framework!

Many IoC containers require some degree of reflection to run properly. For example:

public class FileValidator
{
    public FileValidator(ILogger logger) { ... }
}

// client code
var validator = IoC.Resolve<FileValidator>();

Our IoC container will instantiate a file validator and pass an appropriate implementation of ILogger into the constructor. Which implementation? That depends on how its implemented.

Let's say that I gave the name of the assembly and class in a configuration file. The language needs to read name of the class as a string and use reflection to instantiate it.

Unless we know the implementation at compile time, there is no type-safe way to instantiate a class based on its name.

Late Binding / Duck Typing

There are all kinds of reasons why you'd want to read the properties of an object at runtime. I'd pick logging as the simplest use case -- let say you were writing a logger which accepts any object and spits out all of its properties to a file.

public static void Log(string msg, object state) { ... }

You could override the Log method for all possible static types, or you could just use reflection to read the properties instead.

Some languages like OCaml and Scala support statically-checked duck-typing (called structural typing), but sometimes you just don't have compile-time knowledge of an objects interface.

Or as Java programmers know, sometimes the type system will get your way and require you to write all kinds of boilerplate code. There's a well-known article which describes how many design patterns are simplified with dynamic typing.

Occasionally circumventing the type system allows you to refactor your code down much further than is possible with static types, resulting in a little bit cleaner code (preferably hidden behind a programmer friendly API :) ). Many modern static languages are adopting the golden rule "static typing where possible, dynamic typing where necessary", allowing users to switch between static and dynamic code.


Projects such as hibernate (O/R mapping) and StructureMap (dependency injection) would be impossible without Reflection. How would one solve these with polymorphism alone?

What makes these problems so difficult to solve any other way is that the libraries don't directly know anything about your class hierarchy - they can't. And yet they need to know the structure of your classes in order to - for example - map an arbitrary row of data from a database to a property in your class using only the name of the field and the name of your property.

Reflection is particularly useful for mapping problems. The idea of convention over code is becoming more and more popular and you need some type of Reflection to do it.

In .NET 3.5+ you have an alternative, which is to use expression trees. These are strongly-typed, and many problems that were classically solved using Reflection have been re-implemented using lambdas and expression trees (see Fluent NHibernate, Ninject). But keep in mind that not every language supports these kinds of constructs; when they're not available, you're basically stuck with Reflection.

In a way (and I hope I'm not ruffling too many feathers with this), Reflection is very often used as a workaround/hack in Object-Oriented languages for features that come for free in Functional languages. As functional languages become more popular, and/or more OO languages start implementing more functional features (like C#), we will most likely start to see Reflection used less and less. But I suspect it will always still be around, for more conventional applications like plugins (as one of the other responders helpfully pointed out).


Actually, you are already using a reflective system everyday: your computer.

Sure, instead of classes, methods and objects, it has programs and files. Programs create and modify files just like methods create and modify objects. But then programs are files themselves, and some programs even inspect or create other programs!

So, why is it so OK for a Linux install to be reflexive that nobody even thinks about it, and scary for OO programs?