views:

1030

answers:

6

I have wondered about the appropriateness of reflection in C# code. For example I have written a function which iterates through the properties of a given source object and creates a new instance of a specified type, then copies the values of properties with the same name from one to the other. I created this to copy data from one auto-generated LINQ object to another in order to get around the lack of inheritance from multiple tables in LINQ.

However, I can't help but think code like this is really 'cheating', i.e. rather than using using the provided language constructs to achieve a given end it allows you to circumvent them.

To what degree is this sort of code acceptable? What are the risks? What are legitimate uses of this approach?

A: 

My best advice is to refer you to this discussion, where we talked over the same merits:

http://stackoverflow.com/questions/27294/abstract-factory-design-pattern

FlySwat
+2  A: 

It may be just me, but the way I'd get into this is by creating a code generator - using reflection at runtime is a bit costly and untyped. Creating classes that would get generated according to your latest code and copy everything in a strongly typed manner would mean that you will catch these errors at build-time.

For instance, a generated class may look like this:

static class AtoBCopier
{
    public static B Copy(A item)
    {
        return new B() { Prop1 = item.Prop1, Prop2 = item.Prop2 };
    }
}

If either class doesn't have the properties or their types change, the code doesn't compile. Plus, there's a huge improvement in times.

Omer van Kloeten
+1  A: 

I agree, it gives me the it works but it feels like a hack feeling. I try to avoid reflection whenever possible. I have been burned many times after refactoring code which had reflection in it. Code compiles fine, tests even run, but under special circumstances (which the tests didn't cover) the program blows up run-time because of my refactoring in one of the objects the reflection code poked into.

Example 1: Reflection in OR mapper, you change the name or the type of the property in your object model: Blows up run-time.

Example 2: You are in a SOA shop. Web Services are complete decoupled (or so you think). They have their own set of generated proxy classes, but in the mapping you decide to save some time and you do this:

ExternalColor c = (ExternalColor)Enum.Parse(typeof(ExternalColor), 
                                            internalColor.ToString());

Under the covers this is also reflection but done by the .net framework itself. Now what happens if you decide to rename InternalColor.Grey to InternalColor.Gray? Everything looks ok, it builds fine, and even runs fine.. until the day some stupid user decides to use the color Gray... at which point the mapper will blow up.

Bjorn Reppen
+4  A: 

Sometimes using reflection can be a bit of a hack, but a lot of the time it's simply the most fantastic code tool.

Look at the .Net property grid - anyone who's used Visual Studio will be familiar with it. You can point it at any object and it it will produce a simple property editor. That uses reflection, in fact most of VS's toolbox does.

Look at unit tests - they're loaded by reflection (at least in NUnit and MSTest).

Reflection allows dynamic-style behaviour from static languages.

The one thing it really needs is duck typing - the C# compiler already supports this: you can foreach anything that looks like IEnumerable, whether it implements the interface or not. You can use the C#3 collection syntax on any class that has a method called Add.

Use reflection wherever you need dynamic-style behaviour - for instance you have a collection of objects and you want to check the same property on each.

The risks are similar for dynamic types - compile time exceptions become run time ones. You code is not as 'safe' and you have to react accordingly.

The .Net reflection code is very quick, but not as fast as the explicit call would have been.

Keith
+1  A: 

I recently used reflection in C# for finding implementations of a specific interface. I had written a simple batch-style interpreter that looked up "actions" for each step of the computation based on the class name. Reflecting the current namespace then pops up the right implementation of my IStep inteface that can be Execute()ed. This way, adding new "actions" is as easy as creating a new derived class - no need to add it to a registry, or even worse: forgetting to add it to a registry...

Daren Thomas
+1  A: 

Reflection is a wonderful tool that I could not live without. It can make programming much easier and faster.

For instance, I use reflection in my ORM layer to be able to assign properties with column values from tables. If it wasn't for reflection I have had to create a copy class for each table/class mapping.

As for the external color exception above. The problem is not Enum.Parse, but that the coder didnt not catch the proper exception. Since a string is parsed, the coder should always assume that the string can contain an incorrect value.

The same problem applies to all advanced programming in .Net. "With great power, comes great responsibility". Using reflection gives you much power. But make sure that you know how to use it properly. There are dozens of examples on the web.

jgauffin