Invoking Constructors


The previous example dynamically called the methods of an object; however, that object was constructed in a normal manner. This means a hybrid of techniques were used. To be more consistent, the class will be constructed dynamically as well. The next example does this.

// Runtime7 - Calling Constructors

using System;
using System.Reflection;

class X
{
    public int x;
    public int y;

    public X(int i) { x = i; y = i; }

    public X(int i, int j) { x = i; y = j; }

    public int Sum() { return x + y; }

    public void Set(int i, int j)
    {
        x = i; y = j;
        Console.WriteLine("In Set(int,int), value={0}", this);
    }

    public void Set(double u, double v)
    {
        x = (int)u; y = (int)v;
        Console.WriteLine("In Set(double,double), value={0}", this);
    }

    public override string ToString()
    {
        return "(" + x + "," + y + ")";
    }
}

class Program
{
    static void Main()
    {
        Type t = typeof(X);

        ConstructorInfo[] constructors = t.GetConstructors();

        Console.WriteLine("Constructors are as follows");

        foreach (ConstructorInfo ci in constructors)
        {
            Console.Write(t.Name + "(");

            ParameterInfo[] parameters = ci.GetParameters();

            for (int i=0; i<parameters.Length; i++)
            {
                Console.Write(parameters[i].ParameterType.Name + " " +
                              parameters[i].Name);

                if (i+1 < parameters.Length) Console.Write(",");
            }
            
            Console.WriteLine(")");
        }

        int j;
        for (j = 0; j < constructors.Length; j++)
        {
            ParameterInfo[] parameters = constructors[j].GetParameters();
            if (parameters.Length == 2) break;
        }

        if (j == constructors.Length)
        {
            Console.WriteLine("No matching constructor was found.");
            return;
        }
        else
        {
            Console.WriteLine("Constructor with two parameters located");

            object[] arguments = new object[2];
            arguments[0] = 10;
            arguments[1] = 20;

            object o = constructors[j].Invoke(arguments);
            
            Console.WriteLine("Invoking methods of {0}", t.Name);

            MethodInfo[] methods = t.GetMethods();

            foreach (MethodInfo mi in methods)
            {
                ParameterInfo[] parameters = mi.GetParameters();

                if (mi.Name.CompareTo("Set") == 0 &&
                    parameters[0].ParameterType == typeof(int))
                {
                    object[] args = new object[2];
                    args[0] = 9;
                    args[1] = 18;
                    mi.Invoke(o, args);
                }

                else if (mi.Name.CompareTo("Set") == 0 &&
                    parameters[0].ParameterType == typeof(double))
                {
                    object[] args = new object[2];
                    args[0] = 1.5;
                    args[1] = 2.5;
                    mi.Invoke(o, args);
                }

                else if (mi.Name.CompareTo("Sum") == 0)
                {
                    int v = (int)mi.Invoke(o, null);
                    Console.WriteLine("Sum for {0} = {1}", o, v);
                }
            }
        }

    }
}

The output of this program is shown below.

Constructors are as follows
X(Int32 i)
X(Int32 i,Int32 j)
Constructor with two parameters located
Invoking methods of X
Sum for (10,20) = 30
In Set(int,int), value=(9,18)
In Set(double,double), value=(1,2)

The method of Type, GetConstructors() is used to obtain an array of constructors. The general form of this method is:

ConstructorInfo[] GetConstructors()

The array of ConstructorInfo structures describes the constructors of class X. The class ConstructorInfo derives from the abstract class MethodBase, which inherits from MemberInfo. The method GetParameters() of ConstructorInfo returns a list of parameters for a constructor.

The array of ConstructorInfo structures is used to construct an object of class X. A constructor with two parameters is chosen and an object is created dynamically through that constructor. The method Invoke() of a ConstructorInfo may be used to call the constructor. The general form of Invoke() is as follows.

object Invoke(object[] arguments)

For a parameterless constructor, arguments is set to null. The object returned is an object of the specified class (X in this case).