C# · Dotnet

Refactoring: Enums with ExtensionMethods

Dear Reader,

Today i had to do some unit testing of a class which had some private instance and static methods along with non privates in it. These methods had some good core logic in it which i determined to do unit testing. Though many articles and experts say that its ok not to do so for a private method,Β  but i wanted my logic to be fail proof. Hence only way to do this is to use reflection APIs to access the private members.

Below is the simulated code (for article sake) shown which needs to be tested:

class ToBeUnitTested
    {
        private void PrivateMethod()
        {
            //Some business code logic
        }

        private static void StaticMethod()
        {
            //Some business code logic
        }
    }

So, i started to write the unit testing code which had the reflection APIs to invoke these members. Instead of embedding the reflection code in my unit test class, i refactored it to a helper class as shown below:

class Helper
    {
        private Helper() { }

        public static void InvokePrivateMethod(Type type,
            string methodName, object instance, object[] parameters)
        {
            BindingFlags flags = BindingFlags.Instance | 
                BindingFlags.InvokeMethod | BindingFlags.NonPublic;

            RunMethod(type, methodName, instance, parameters, flags);
        }

        public static void InvokePrivateStaticMethod(Type type,
            string methodName, object[] parameters)
        {
            BindingFlags flags = BindingFlags.InvokeMethod |
                BindingFlags.NonPublic | BindingFlags.Static;
            RunMethod(type, methodName, null, parameters, flags);
        }        private static void RunMethod(Type type, string methodName, 
            object instance, object[] parameters, BindingFlags flags)
        {
            //Reflection code
        }
    }

As shown above code, i have couple of public helper methods for private instance and private static. Of course i had couple more for protected , etc. But shown only 2 for simplicity sake. As you can see in the above code, i have more methods for each of the method with different access modifiers in my testable class. I some how did not like the way it is done above. I just wanted the helper class to be simple and concise with only one method rather than 3 methods. The only changing thing is the BindingFlags combination. So i decided to do a bit of refactoring and having only single method RunMethod(….) in the helper class which is very simple and understandable for Helper class.

To do this refactoring, i though of using Enum to specify combination choice for PrivateInstance and PrivateStatic, etc. But BindingFlags is already an Enum. So Enum for Enum is not a good choice and makes it more difficult to understand. Hence the next thing occurred to me was to use Extension methods with Enum. I really like how the Extension method offers a great deal of flexibility and maintainability of the code.
Below is the refactored code:

public static class BindingFlagsExtension
    {
        public static BindingFlags GetInstancePrivateMethodFlags(this BindingFlags flags)
        {
            return BindingFlags.Instance |
                BindingFlags.InvokeMethod | BindingFlags.NonPublic;
        }

        public static BindingFlags GetStaticPrivateMethodFlags(this BindingFlags flags)
        {
            return BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Static;
        }
    }

    class Helper
    {
        private Helper() { }        public static void InvokeMethod(Type type, string methodName,
            object instance, object[] parameters,BindingFlags flags)
        {
            //Invoke reflection code
        }
    }

Now the helper class became very simple and very concise too, even Helper class adheres much more towards SOC principle. Even maintaining and extension of the code (SOLID principle) for Helper and Extension class is high.

In fact i feel good that i did some thing cool today, though its not amazing one. Love to hear suggestions. So please feel free to comment on other ways of improvement.

Thanks & Happy Coding,
Zen πŸ™‚

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s