Jul 3, 2014

C# Get and set value using reflection

//In this post I will explain how to set and get value of members via reflection in c#.

    //For this example I have created one class with private, public static members.

    public class TestClass
    {
        //member variables
        private int m_var1 = 0;
        private static int m_var2 = 0;
        public int m_var3 = 0;
        public static int m_var4 = 0;
        public static readonly int m_var5 = 0;

        public TestClass()
        {
            Console.WriteLine("Parameterless constructor");
        }

        public TestClass(int param1)
        {
            Console.WriteLine("Parameterized constructor");
        }


        private TestClass(string param1)
        {
            Console.WriteLine("Parameterized constructor");
        }

        public void Method1(int arg1, string arg2)
        {
            Console.WriteLine("Public instance method \"Method 1\" with two arguments");
        }

        public static void Method2(int arg1, string arg2)
        {
            Console.WriteLine("Static method \"Method 2\" with two arguments");
        }

        private void Method3(int arg1)
        {
            Console.WriteLine("Private instance method \"Method 3\" with one argument");
        }

        private static void Method4(int arg1)
        {
            Console.WriteLine("private static method \"Method 4\" with one argument");
        }
    }

    public class ReflectionHelper
    {
        //classType :- Type that contains members
        //memberName:- Name of the member i.e. Name of field or property or method. Note:- Empty or null for constructors. 
        //bindingFlags:- Used to filter members based on their visibility and access modifiers. ie. static, readonly, private, Inherited members. For a list of possibilities refer to 
        //target:- The object on which member to invoke. In short object that contains members to invoke. Not required when invoking static members or constructors.
        //args:- Arguments required when invoking members. Empty array for no argument.

        public static void InvokeMember(Type classType, string memberName, System.Reflection.BindingFlags bindingFlags, object target, object[] args)
        {
            classType.InvokeMember(memberName, bindingFlags, null, target, args);
        }

    }

    public static class Test
    {
        static readonly Type classType = typeof(TestClass);

        public static void Invoke()
        {

            //To invoke public parameterless constructor,

            ReflectionHelper.InvokeMember(classType, string.Empty, System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.CreateInstance, null, new object[0]);

            //For parameterized constructors just pass parameter values in last argument.

            //To Invoke public parameterized constructor,

            ReflectionHelper.InvokeMember(classType, string.Empty, System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.CreateInstance, null, new object[] { 1 });

            //With combination of BindingFlags you can invoke private constructors also.

            //For example,

            ReflectionHelper.InvokeMember(classType, string.Empty,
            System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.CreateInstance, null, new object[] { "1" });

            //To Invoke static method with single arguments
            ReflectionHelper.InvokeMember(classType, "TestMethod1",
            System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, null, new object[] { "1" });

            //To get static field value
            ReflectionHelper.InvokeMember(classType, "m_var4",
            System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetField, null, new object[] { });


            //To get instance field value
            var target = new TestClass();
            ReflectionHelper.InvokeMember(classType, "m_var3",
            System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.GetField, target, new object[] { });

            //To set static field value
            ReflectionHelper.InvokeMember(classType, "m_var4",
            System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.SetField, null, new object[] { });


            //To set instance field value

            ReflectionHelper.InvokeMember(classType, "m_var3",
            System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.SetField, target, new object[] { 1 });



            There are pros and cons of this approach.

            Pros:-

            1). I do not need to know structure of class before accessing it. I can access almost any member with public, private, protected access modifiers. I can even set value of readonly variables. Though it defeats purpose of language specific features.

            Cons:-

            1). Execution speed is slower then direct access.

            Please let me know if this post is useful or not.
        }
    }

No comments:

Post a Comment