Posted by: Zeeshan Amjad | October 12, 2011

Calling private methods using Reflection


We just saw how we how to call a member function using the reflection here. With this method we can also call private member function of the class even static function. InvokeMember is defined in Type class, which is a child of abstract class MemberInfo. Here is a class diagram of it.

TypeHierarchy

Type class implement two interface _Type and IReflect. There are lots of methods in these interface, therefore Type class has lots of methods. Here is a class diagram of IReflect interface.

IReflect

and here is a class diagram of _Type interface.

_Type

This is a class diagram of Type class.

Type

Now suppose if we have a C# class that has both public and private static and non static method. Here is our class.

Code Snippet
class MyClass
{
    public void InstanceMethod()
    {
        Console.WriteLine("Instance Method");
    }

    private void PrivateInstanceMethod()
    {
        Console.WriteLine("Private Instance Method");
    }

    public static void StaticMethod()
    {
        Console.WriteLine("Static Method");
    }

    private static void PrivateStaticMethod()
    {
        Console.WriteLine("Private Static Method");
    }
}

 

Here is a code to call these methods using reflection.

Code Snippet
typeof(MyClass).InvokeMember("StaticMethod",
    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
    null, null, null);

typeof(MyClass).InvokeMember("PrivateStaticMethod",
    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.NonPublic,
    null, null, null);

MyClass obj = new MyClass();

typeof(MyClass).InvokeMember("InstanceMethod",
    BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
    null, obj, null);

typeof(MyClass).InvokeMember("PrivateInstanceMethod",
    BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic,
    null, obj, null);

In same way if we want to pass parameter into the method, it is not difficult. If we have a method like this.

Code Snippet
public static void DisplayMessage(int no, string msg)
{
    for (int i = 0; i < no; i++)
        Console.WriteLine(msg);
}

 

We can call it something like this.

Code Snippet
typeof(MyClass).InvokeMember("DisplayMessage",
    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
    null, obj, new object[] { 3, "hello world"});

 

If method returns something, still it is very easy to call, we just have to typecast the result in appropriate data type. Here is our method.

Code Snippet
public static int Factorial(int no)
{
    if (no < 0)
        return -1;

    if (no == 0)
        return 1;
    else
        return no * Factorial(no – 1);
}

 

And here is a call of this method using reflection.

Code Snippet
int result = (int)typeof(MyClass).InvokeMember("Factorial",
    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
    null, obj, new object[] { 5 });

Console.WriteLine(result);

 

If we have our or ref parameter then we can call it similar way, the only difference is we have to create a named array of parameter unlike unnamed array. Here is our method with one our and one ref parameter.

Code Snippet
public static void OutRefExample(out int data1, ref int data2)
{
    data1 = 10;
    data2 = 20;
}

 

Here is a usage of it.

Code Snippet
object[] param = new object[2];

typeof(MyClass).InvokeMember("OutRefExample",
    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
    null, obj, param);

Console.WriteLine(param[0]);
Console.WriteLine(param[1]);

 

Here is a complete code of our example.

Code Snippet
using System;
using System.Reflection;

namespace Reflection
{
    class Program
    {

        static void Main(string[] args)
        {            
            try
            {

                typeof(MyClass).InvokeMember("StaticMethod",
                    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
                    null, null, null);

                typeof(MyClass).InvokeMember("PrivateStaticMethod",
                    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.NonPublic,
                    null, null, null);

                MyClass obj = new MyClass();

                typeof(MyClass).InvokeMember("InstanceMethod",
                    BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
                    null, obj, null);

                typeof(MyClass).InvokeMember("PrivateInstanceMethod",
                    BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic,
                    null, obj, null);

                typeof(MyClass).InvokeMember("DisplayMessage",
                    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
                    null, obj, new object[] { 3, "hello world"});

                int result = (int)typeof(MyClass).InvokeMember("Factorial",
                    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
                    null, obj, new object[] { 5 });

                Console.WriteLine(result);

                object[] param = new object[2];

                typeof(MyClass).InvokeMember("OutRefExample",
                    BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public,
                    null, obj, param);

                Console.WriteLine(param[0]);
                Console.WriteLine(param[1]);

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

    class MyClass
    {
        public void InstanceMethod()
        {
            Console.WriteLine("Instance Method");
        }

        private void PrivateInstanceMethod()
        {
            Console.WriteLine("Private Instance Method");
        }

        public static void StaticMethod()
        {
            Console.WriteLine("Static Method");
        }

        private static void PrivateStaticMethod()
        {
            Console.WriteLine("Private Static Method");
        }

        public static void DisplayMessage(int no, string msg)
        {
            for (int i = 0; i < no; i++)
                Console.WriteLine(msg);
        }

        public static int Factorial(int no)
        {
            if (no < 0)
                return -1;

            if (no == 0)
                return 1;
            else
                return no * Factorial(no – 1);
        }

        public static void OutRefExample(out int data1, ref int data2)
        {
            data1 = 10;
            data2 = 20;
        }
    }
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

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

Categories

%d bloggers like this: