Update 8/10/2011: this project now has a home at https://github.com/davidebbo/ReflectionMagic. Also, it is installable via nuget. It's named 'ReflectionMagic'.

 

Private reflection allows you to access private and internal members in other assemblies.  Generally, it’s considered to be a bad thing to do, as it ties you to undocumented implementation details which can later break you.  Also, it’s not usable in medium trust (and neither is the technique I describe in this post).

My purpose in this post is not to encourage anyone to use private reflection in situations where you would not have done it anyway.  Instead, my purpose is to show you how to do it much more easily if you decide that you need to use it.  Putting it a different way, I’m not telling you to break the law, but I’m telling you how to break the law more efficiently if that’s what you’re into!

Ok, that was my little disclaimer to avoid getting in trouble.  My lawyer made me do it!  Or would have if I had one. :)

The scenario

So let’s look at a sample scenario.  Say you’re using an assembly that has code like this:

public class Foo1 {    private Foo2 GetOtherClass() { ... }}internal class Foo2 {    private string SomeProp { get { .. } }}

And say you have an instance foo1 of the public class Foo1 and your evil self tells you that you want to call the private method GetOtherClass() and then get the SomeProp property off of that.

The solution using good old private reflection

Here is how you can write this code the old fashion way using private reflection.

object foo2 = typeof(Foo1).InvokeMember("GetOtherClass",    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,    null, foo1, null);PropertyInfo propInfo = foo2.GetType().GetProperty("SomeProp",    BindingFlags.Instance | BindingFlags.NonPublic);string val = (string)propInfo.GetValue(foo2, null);

Sure that works, but ouch, that’s ugly!

The dynamic solution

Now to be clear, C# 4.0 dynamic is not going to help you with this out of the box, because it doesn’t support private reflection (I suppose the C# designers didn’t want to encourage that).  So if you try to write:

string val = ((dynamic)foo1).GetOtherClass().SomeProp;

This will blow up with the error “RuntimeBinderException: 'LibraryWithPrivateMembers.Foo1.GetOtherClass()' is inaccessible due to its protection level”.

To get around this, we need to write our own DynamicObject implementation which will perform private reflection under the cover.  With that library, we can now write (after importing the PrivateReflectionUsingDynamic namespace):

string val = foo1.AsDynamic().GetOtherClass().SomeProp;

So we call AsDynamic() on our object (it’s an extension method), which gets us our special DynamicObject implementation.  Once we have that, we can happily write a tiny bit of nice looking dynamic code to replace the ugly reflection mess!

How does it all work

I attached a full VS2010 solution with unit test coverage, so I’m not going to show you the whole code here (it’s over 200 lines).  Instead, I’ll describe it at a high level.

I actually wrote a few other posts before where I wrote custom DynamicObject implementation (named PrivateReflectionDynamicObject).  The general idea is that you override various methods that get called by the dynamic engine when it needs to execute the code.  e.g. when it needs to get a property value, it calls your TryGetMember method.  To call a method, it calls your TryInvokeMember method.

The difference between my previous posts and what I did here is that PrivateReflectionDynamicObject is much more complete, because it’s trying to handle most of the things you might want to using private reflection.  Specifically, it handles:

  • Getting and setting properties
  • Getting and setting fields (note that properties and fields are the same thing in the dynamic world, but different in the reflection world)
  • Calling methods
  • Getting and setting values into arrays
  • Getting and setting values into indexed properties (e.g. string this[string s] { … })
  • Type conversions

The implementation of all this is simply to turn around and use private reflection.  So in the end, you’re executing mostly the same code as if you had done it manually, but with a lot less pain.

One interesting thing to note is that objects returned by this logic need to be themselves wrapped into a PrivateReflectionDynamicObject.  This is necessary in order to able to write foo1.AsDynamic().GetOtherClass().SomeProp.  Otherwise, GetOtherClass() would just return a Foo2 object, and you would not be able to access the SomeProp property.  In a twisted way, you might call that a fluent API.

And finally, then there is the AsDynamic extension method, which makes it easy to access this functionality.  It just has:

public static class PrivateReflectionDynamicObjectExtensions {    public static dynamic AsDynamic(this object o) {        return PrivateReflectionDynamicObject.WrapObjectIfNeeded(o);    }}

Usually, I’m hesitant to add extension methods to object, but in this case it seemed appropriate, since you can potentially do private reflection on any object.  Also, it’s in a specific namespace, so the method only shows up if you choose to import it.

You can unzip the attach solution and try it on VS2010.  I have a somewhat newer build, but I think it should run on beta 2.