Invoking Methods by Using the MethodInfo Class

The Reflection API also provides the ability to search for and invoke methods that you may not have knowledge of at compile time. Before you can invoke a method, you must successfully request a MethodInfo object from the Type object. In this section we will investigate three ways to retrieve a MethodInfo from a Type object.

Working with the GetMethod Method

The easiest way to retrieve a MethodInfo object is to search for the method by name. The Type object provides the GetMethod(string methodName) to do just this. The string parameter contains the case-sensitive name of the public method to get. If you request a nonpublic method or a method that does not exist, then a null reference is returned. Beware that for overloaded methods an AmbiguousMatchException will be thrown. Listing 13.11 demonstrates how to find a specific method by name.

Listing 13.11.
C#
public class Type_GetMethod {
  public int m_Integer;
  public string m_String;

  public Type_GetMethod(int i, string s) {
    m_Integer = i;
    m_String = s;
  }

  public int GetSecretCode() {
    char[] chars = m_String.ToCharArray();
    int charsLength = chars.Length;
    int ret = m_Integer;

    for (int i = 0; i < charsLength; ++i)
      ret += (int)chars[i];

    return ret;
  }

  public static void Main() {
    Type t = typeof(Type_GetMethod);
    MethodInfo methodInfo = t.GetMethod("GetSecretCode");

    if (methodInfo == null) {
      MessageBox.Show("Could not find the GetSecretCode method.");
      return;
    }

    MessageBox.Show(
      String.Format("Found {0} method name {1}",
      (methodInfo.IsPublic ? "Public" : "Non-Public"),
      methodInfo.Name));
  }
}
VB
Module Module1
    Public Class Type_GetMethod
        Public m_Integer As Int32
        Public m_String As String

        Public Sub New(ByVal i As Int32, ByVal s As String)
            m_Integer = i
            m_String = s
        End Sub

        Public Function GetSecretCode() As Int32
            Dim chars = m_String.ToCharArray()
            Dim charsLength = chars.Length
            Dim ret = m_Integer
            Dim i As Int32

            For i = 0 To charsLength
                ret = ret + CInt(chars(i))
            Next i
        End Function
    End Class

    Public Sub Main()
        Dim tgm = New Type_GetMethod(0, 0)
        Dim t = tgm.GetType()
        Dim methodInfo = t.GetMethod("GetSecretCode")
        Dim visibility As String

        If MethodInfo Is Nothing Then
            MessageBox.Show("Could not find the " & _
                            "GetSecretCode method.")
            Return
        End If

        If MethodInfo.IsPublic Then
            visibility = "Public"
        Else
            visibility = "Non-Public"
        End If

        MessageBox.Show( _
            String.Format("Found {0} method name {1}", _
            visibility, _
            methodInfo.Name))
    End Sub
End Module

FIND MethodInfo OBJECTS FOR OVERLOADED METHODS

An overload of the GetMethod method exists that can also handle searching for overloaded methods. This overload allows you to look up a public method by name and by the type of parameters it accepts. Listing 13.12 demonstrates how to search for an overloaded method.

Listing 13.12.
C#
public class Type_GetMethod {
  public void OverloadedMethod(int param1) {
  }

  public void OverloadedMethod(int param1, bool param2) {
  }
}

public class Test {
  public static void Main() {
    Type t = typeof(Type_GetMethod);
    Type[] args = {typeof(int), typeof(bool)};
    MethodInfo methodInfo = t.GetMethod("OverloadedMethod", args);

    if (methodInfo == null) {
      MessageBox.Show("Could not find the OverloadedMethod method.");
        return;
    }

    MessageBox.Show(
      String.Format("Found {0} method name {1}",
        (methodInfo.IsPublic ? "Public" : "Non-Public"),
         methodInfo.Name));
  }
}

VB
Module Module1
    Public Class Type_GetMethod
        Public Sub OverloadedMethod(ByVal param1 As Int32)
        End Sub

        Public Sub OverloadedMethod(ByVal param1 As Int32, _
ByVal param2 As Int32)
        End Sub
    End Class

    Public Sub Main()
        Dim tgm As New Type_GetMethod()
        Dim t = tgm.GetType()
        Dim args() = New Type() {0.GetType(), 0.GetType()}
        Dim methodInfo = t.GetMethod("OverloadedMethod", args)
        Dim visibility As String

        If methodInfo Is Nothing Then
            MessageBox.Show("Could not find the " & _
                            "OverloadedMethod method.")
            Return
        End If

        If methodInfo.IsPublic Then
            visibility = "Public"
        Else
            visibility = "Non-Public"
        End If

        MessageBox.Show( _
            String.Format("Found {0} method name {1}", _
            visibility, _
            methodInfo.Name))
    End Sub
End Module


Another overload of the GetMethod method allows you to search for a method by name and by a set of binding constraints. The binding constraints are specified by passing a combination of BindingFlags values. Just like with GetType, there is a list of BindingFlags values that affects the execution of the search for the method. The BindingFlags values that affect the GetMethod method fall into two categories: those that define which methods to include in the search and those that change how the search works. Table 13.2 shows the list of BindingFlags values that define which methods to include in the search. Table 13.3 lists those that change how the search works.

Table 13.2. BindingFlags Members that Define Which Methods Are Searched via GetMethod
MEMBERDESCRIPTION
InstanceIncludes instance methods in the search
StaticIncludes static methods in the search
PublicIncludes public methods in the search
NonPublicIncludes private and protected methods in the search
FlattenHierarchyIncludes static methods up the class hierarchy

Table 13.3. BindingFlags Members That Change How GetMethod Searches
MEMBERMEANING
IgnoreCaseIgnores the case of the specified name parameter
DeclaredOnlySearches only the methods declared on the current Type and not methods that were inherited

The BindingFlags enumeration values can be bitwise combined to allow a very flexible way to customize the search for a desired method. If the request type is nonpublic or does not exist, then null will be returned. Listing 13.13 demonstrates how to find a public static method by using a case-insensitive search.

Listing 13.13.
C#
public class Type_GetMethod {
  public static void StaticMethod() {
  }

  public void InstanceMethod(){
  }
}

public class Test {
  public static void Main() {
    Type t = typeof(Type_GetMethod);
    BindingFlags flags =
      BindingFlags.Static|BindingFlags.Public|BindingFlags.IgnoreCase;

    MethodInfo methodInfo = t.GetMethod("sTaTiCmEtHoD", flags);
    if (methodInfo == null) {
      MessageBox.Show("Could not find the method named StaticMethod.");
        return;
    }

    MessageBox.Show(
      String.Format("Found {0} {1} method name {2}",
        (methodInfo.IsPublic ? "public" : "non-public"),
        (methodInfo.IsStatic ? "static" : "Instance"),
         methodInfo.Name));
  }
}

VB
Module Module1
    Public Class Type_GetMethod
        Public Shared Sub SharedMethod()
        End Sub

        Public Sub InstanceMethod()
        End Sub
    End Class

    Public Sub Main()
        Dim tgm = New Type_GetMethod()
        Dim t = tgm.GetType()
        Dim flags = BindingFlags.Static Or _
                    BindingFlags.Public Or _
                    BindingFlags.IgnoreCase
        Dim methodInfo = t.GetMethod("sHaReDmEtHoD", flags)
        Dim visibility As String
        Dim isShared As String

        If methodInfo Is Nothing Then
            MessageBox.Show("Could not find the SharedMethod method.")
            Return
        End If

        If methodInfo.IsPublic Then
            visibility = "Public"
        Else
            visibility = "Non-Public"
        End If

        If methodInfo.IsStatic Then
            isShared = "Shared"
        Else
            isShared = "Instance"
        End If

        MessageBox.Show( _
            String.Format("Found {0} {1} method name {2}", _
            visibility, isShared, methodInfo.Name))
    End Sub
End Module

Invoking a Method with the MethodInfo Class

Now that you have learned how to retrieve a MethodInfo object by searching over Type object, we can now investigate how to invoke that method. Much like the ConstructorInfo class, the MethodInfo class provides the Invoke method to allow users to invoke the method it reflects. The Invoke method accepts two parameters. The first parameter represents an instance of the type on which the method exists. The second parameter is an array of objects that represent the methods argument list. For methods that do not accept parameters, you can pass an empty array of objects. The Invoke method returns an object that represents the return value of the function. If the method does not have a return value, then null is returned. Listing 13.14 demonstrates how to invoke a method through a MethodInfo object.

Listing 13.14.
C#
public class MethodInfo_Invoke {
  public int AddParameterValues(int bar, int zoo) {
       return bar + zoo;
  }
}

public class Test {
  public static void Main() {
    Type t = typeof(MethodInfo_Invoke);
    Type[] argTypes = {typeof(int), typeof(int)};
    MethodInfo methodInfo =
      t.GetMethod("AddParameterValues", argTypes);

    if (methodInfo == null) {
      MessageBox.Show("Could not find the AddParameterValues method.");
        return;
    }

    MethodInfo_Invoke c = new MethodInfo_Invoke();
    Object[] argValues = {1, 1};
    object ret = methodInfo.Invoke(c, argValues);

    if(ret == null)
      MessageBox.Show("The invoked method returned null");
    else
      MessageBox.Show("The invoked method returned " + ret);
  }
}

VB
Module Module1
    Public Class MethodInfo_Invoke
        Public Function AddParameterValues(ByVal bar As Int32, _
                                           ByVal zoo As Int32)
            Return (bar + zoo)
        End Function
    End Class

    Public Sub Main()
        Dim mii = New MethodInfo_Invoke()
        Dim t = mii.GetType()
        Dim argTypes() = New Type() {0.GetType(), 0.GetType}
        Dim MethodInfo = t.GetMethod("AddParameterValues", argTypes)

        If MethodInfo Is Nothing Then
            MessageBox.Show("Could not find the " & _
                            "AddParameterValues method.")
            Return
        End If

        Dim c As New MethodInfo_Invoke()
        Dim argValues() = New Object() {1, 1}
        Dim ret = MethodInfo.Invoke(c, argValues)

        If ret Is Nothing Then
            MessageBox.Show("The invoke method returned nothing")
        Else
            MessageBox.Show("The invoke method returned " & _
                            ret.ToString())
        End If
    End Sub
End Module

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.209.201