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.
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.
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 METHODSAn 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.
|
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.
MEMBER | DESCRIPTION |
---|---|
Instance | Includes instance methods in the search |
Static | Includes static methods in the search |
Public | Includes public methods in the search |
NonPublic | Includes private and protected methods in the search |
FlattenHierarchy | Includes static methods up the class hierarchy |
MEMBER | MEANING |
---|---|
IgnoreCase | Ignores the case of the specified name parameter |
DeclaredOnly | Searches 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.
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 |
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.
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 |
13.58.209.201