Wednesday, May 15, 2013

Thug Access

Have you ever gotten this kind of question in an interview? What do "private", "protected", and "internal" keywords in C# do? And you wanted to answer, "Nothing mother-freller! I am a mother-frelling thug and I have thug access hazmot!"

So I have started a new side project. (yes, I haven't finished my caching side project, but no one except search engines reads my blog so frell you, robot scanning my text!) Anyway, by combining dynamic objects and reflection you can build a nice little dynamic object that gives you access to methods you wouldn't normally have access to. Here is an example of usage:


TestClass testClass = new TestClass();
dynamic wrapper = new ThugAccess(testClass);
wrapper.PrivateMethod();

Now should you do this? To quote Bryce Lynch, "I only invent the bomb. I don't drop it." The reality is that sometimes you need to access internals. It isn't a common scenario, but you may need to do it and this is a nice way to do it since it hides the reflection code.

Here is what I have so far. Doesn't work for lots of cases so I haven't put it up on github yet. Maybe I will work on it someday. Maybe not.


public class ThugAccess : DynamicObject
{
    const BindingFlags ThugFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
    private object _wrappedObject;

    public ThugAccess(object obj)
    {
        _wrappedObject = obj;
    }
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        result = null;
        Type theType = _wrappedObject.GetType();
        MethodInfo minfo = theType.GetMethod(binder.Name, ThugFlags);
        if (minfo == null)
        {
        return false;
        }
        result = minfo.Invoke(_wrappedObject, args);
        return true;
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;
        Type theType = _wrappedObject.GetType();
        PropertyInfo propertyInfo = theType.GetProperty(binder.Name, ThugFlags);
        if (propertyInfo == null)
        {
            return false;
        }
        result = propertyInfo.GetValue(_wrappedObject,null);
        return true;
    }
    public override bool  TrySetMember(SetMemberBinder binder, object value)
    {
        Type theType = _wrappedObject.GetType();
        PropertyInfo propertyInfo = theType.GetProperty(binder.Name, ThugFlags);
        if (propertyInfo == null)
        {
            return false;
        }
        propertyInfo.SetValue(_wrappedObject, value, null);
        return true;
    }
}



No comments:

Post a Comment