C# 4.0 AccessPrivateWrapper – Instantiate and Access Private/Internal Classes and Members via dynamic + reflection


ANOOP MADHUSUDANAN

Vote on HN

[+] Download Related Source code

I love to see private thingsFrankly, intrusion in to the private space of others is not so great. Mostly, you’ll get a kick in your ass, but at times, if you are lucky and if you are really smart, you’ll end up finding something really cool (Bond, James Bond).

For me, at times, when doing some hacks/exploration of compiled or third party assemblies, I end up wanting to initialize a private class or a class with a private or internal constructor. Or, at times, when dealing with pre-compiled legacy libraries that I can’t change - I want to write a couple of tests against a private method to understand how it works.  I remember going through the source code of TFS power toys or so some time back - and I found that those guys are bringing up a lot of goodness by unearthing some private classes in the TFS library.

Still, I should warn you.

Warning (assume that this is in red): Private types, internals and private members are so because of some reason, and often you don’t want to mess with them directly. And if you do, chances are that you’ll break later, because there is no guarantee that the guys who created those assemblies will keep the private/internal implementations as such.

If you still don’t mind breaking the rules so that you can un earth some hidden potential against all the danger warnings - here is a quick wrapper class that’ll make the job easy using C# 4.0 dynamic features and reflection.  And more than that, this is a good learning point to see how you can use reflection to initialize private types, invoke private/internal constructors, get/set private properties, invoke private methods etc.

1 – What we are talking about

To explain further what we’ll achieve, consider this simple example.

 
class Program
    {
        static void Main(string[] args)
        {
            //Note that the type of 'wrapper' is dynamic
            dynamic wrapper =  new AccessPrivateWrapper(new ClassWithPrivateMembers()) ;

            //Let us access the private members
            wrapper.somePrivateField = "Field Val";
            wrapper.SomePrivateProperty = "Property Val";
            wrapper.DumpValues();

            Console.ReadLine();
        }

        class ClassWithPrivateMembers
        {
            private string somePrivateField;
            private string SomePrivateProperty { get; set; }

            private void DumpValues()
            {
                Console.WriteLine("Look ma, I'm accessing private members. Prop = "
                    + SomePrivateProperty + ", Fld=" + somePrivateField);
            }

        }
    }

And if you run that, you’ll find that the dynamic wrapper is correctly setting the the private field and property values, and then  invoking a private method in the class (DumpValues method), to print the result.

image

No, we are not yet happy. What about accessing private members in private classes in other assemblies? All right, you can use the FromType method of AccessPrivateWrapper to initialize a private/internal class in a different assembly - and you can initilize the class, even if it's constructor is internal or private. Assume that you have a class named 'ClassWithPrivateConstructor' in an assembly, and it is having a private constructor. And you want to create an instance of that, and to invoke some private members inside. This is what you can do.
            //Note that the wrapper is dynamic
            dynamic wrapper = AccessPrivateWrapper.FromType
                (typeof(SomeKnownClass).Assembly,"ClassWithPrivateConstructor");

            //Access the private members
            wrapper.PrivateMethodInPrivateClass();

2 – What the heck is AccessPrivateWrapper

If you are wondering what exactly is AccessPrivateWrapper – it is a simple class we inherited from the System.Dynamic.DynamicObject class.

But before that If the keyword ‘dynamic’s not not familiar to you, I really suggest you to read this article I wrote earlier - C# 4.0 dynamic keyword – Under the hood

Coming back to DynamicObject - In dynamic languages like Ruby, there is an interesting feature called method_missing. Method missing is where your method request will end if the method you called cannot be found.

In .NET 4.0, now you can bring in the same feature, by inheriting your object from the DynamicObject class. What this means is, you'll get notified when a method/property is invoked/accessed on your object. The DynamicObject class has a few cool methods for you to override. For now, we are only interested in these members:

  • TryInvokeMember - Provides the implementation of calling a member.
  • TrySetMember - Provides the implementation of setting a member.
  • TryGetMember - Provides the implementation of getting a member.

So, we are inheriting our AccessPrivateWrapper from the DynamicObject class, and overriding these methods to access private and public methods, properties and fields via reflection (I hope you know the fact that via reflection, you can invoke, set and get the values of even private and internal members).

Have a look at the implementation of AccessPrivateWrapper

/// <summary>
    /// A 10 minute wrapper to access private members, havn't tested in detail.
    /// Use under your own risk - amazedsaint@gmail.com
    /// </summary>
    public class AccessPrivateWrapper : DynamicObject
    {

        /// <summary>
        /// The object we are going to wrap
        /// </summary>
        object _wrapped;
        
        /// <summary>
        /// Specify the flags for accessing members
        /// </summary>
        static BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance 
            | BindingFlags.Static | BindingFlags.Public;

        /// <summary>
        /// Create a simple private wrapper
        /// </summary>
        public AccessPrivateWrapper(object o)
        {
            _wrapped = o;
        }

        /// <summary>
        /// Create an instance via the constructor matching the args 
        /// </summary>
        public static dynamic FromType(Assembly asm,string type,params object[] args)
        {

            var allt = asm.GetTypes();
            var t=allt.First(item=>item.Name==type);


            var types=from a in args
                      select a.GetType();

            //Gets the constructor matching the specified set of args
            var ctor = t.GetConstructor(flags, null, types.ToArray(), null);

            if (ctor != null)
            {
                var instance = ctor.Invoke(args);
                return new AccessPrivateWrapper(instance);
            }

            return null;
        }

        /// <summary>
        /// Try invoking a method
        /// </summary>
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var types=from a in args
                      select a.GetType();

            var method = _wrapped.GetType().GetMethod
                (binder.Name,flags, null, types.ToArray(), null);

            if (method == null)
                return base.TryInvokeMember(binder, args, out result);
            else
            {
                result=method.Invoke(_wrapped, args);
                return true;
            }
        }

        /// <summary>
        /// Tries to get a property or field with the given name
        /// </summary>
        public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
        {
            //Try getting a property of that name
            var prop = _wrapped.GetType().GetProperty(binder.Name,flags);

            if (prop == null)
            {
                //Try getting a field of that name
                var fld = _wrapped.GetType().GetField(binder.Name, flags);
                if (fld != null)
                {
                    result = fld.GetValue(_wrapped);
                    return true;
                }
                else
                    return base.TryGetMember(binder, out result);
            }
            else
            {
                result = prop.GetValue(_wrapped, null);
                return true;
            }
        }

        /// <summary>
        /// Tries to set a property or field with the given name
        /// </summary>
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            var prop = _wrapped.GetType().GetProperty(binder.Name, flags);
            if (prop == null)
            {
                var fld = _wrapped.GetType().GetField(binder.Name, flags);
                if (fld != null)
                {
                    fld.SetValue(_wrapped,value);
                    return true;
                }
                else
                    return base.TrySetMember(binder, value);
            }
            else
            {
                prop.SetValue(_wrapped, value, null);
                return true;
            }
        }

    }

That looks simple, isn’t it? To detail that a bit, when ever user sets or gets a property or field on our dynamic object, the TrySetMember or TryGetMember will get called - and from there onwards, we use reflection to do the job of setting or getting the property or field value, regardless whether it is private or public. If a property of the given name doesn’t exist we’ll try to find a field of the given name to do the get or set operation.

Similarly, TryInvokeMethod will get fired when the user tries to invoke a method via our dynamic wrapper. We fetch the method matching the type of arguments, to obtain the correct overload, and then do the job via reflection. Make sure you download the code from the above link, and debug through a bit.

Also, pay some special attention to the FromType method that we used earlier. Basically, it’ll find the type to create an instance of, and then will find the constructor to invoke, based on the given arguments.

More Thoughts

Now, what about Unit testing your private members? Ever wanted to do that? That is not a common scenario, but at times, as I mentioned earlier, you might be dealing with a legacy system and you want to write a couple of tests against some of the private methods. Oh yes, you can use the AccessPrivateWrapper to do that.

Note that the above implementation don’t work with libraries that are obfuscated, because we are relying on reflection.

Also, the above implementation won’t access inherited private or internal members. That is pretty simple to implement, but that is an exercise for you ;)

Conclusion

A related tip: You can use InternalsVisibleTo attribute to grant access to the internal members of the target assembly to your caller assembly, if you’ve access to both the assemblies. This is useful, especially when you do unit testing.

Also, check out my other C# 4.0 dynamic tricks

 

Happy Coding!!

Shout it
© 2012. All Rights Reserved. Amazedsaint.com