Click here to Skip to main content
Click here to Skip to main content

Dynamically Invoke A Method, Given Strings with Method Name and Class Name

By , 7 Aug 2007
 

Introduction

I recently needed to write some code that would compute the name of a method into a string, and then call that method as shown below:

string s1 = "The";
string s2 = "Method";
string methodName = s1 + s2; // methodName now holds "TheMethod"
    
... code that somehow calls the method whose name is in variable methodName
... in this case, the method TheMethod
    

Like so many things in .NET, this turned out to be easy - as long as you know how to do it.

Simple Solution

Below is the code that will do the trick, wrapped in the method InvokeStringMethod. As you see, it takes only two lines to call another method given its name as a string, and its class name also as a string. Read the comments in the code to see how it works.

public static string InvokeStringMethod(string typeName, string methodName)
{
    // Get the Type for the class
    Type calledType = Type.GetType(typeName);

    // Invoke the method itself. The string returned by the method winds up in s
    String s = (String)calledType.InvokeMember(
                    methodName,
                    BindingFlags.InvokeMethod | BindingFlags.Public | 
                        BindingFlags.Static,
                    null,
                    null,
                    null);

    // Return the string that was returned by the called method.
    return s;
}  

This method assumes that the called method has no parameters and returns a string. Pass the name of the method in parameter methodName, and the name of its class in typeName. For example:

string s = string InvokeStringMethod("TheClass", "TheMethod");

Pass a Parameter to the Called Method

Below is a version that calls a method that expects one parameter of type string.

Have a look at the code. Passing parameters to the called function is simply a matter of passing them to InvokeMember as an array of Objects. InvokeMember in turn passes those objects on as parameters to the called method.

public static string InvokeStringMethod2
    (string typeName, string methodName, string stringParam)
{
    // Get the Type for the class
    Type calledType = Type.GetType(typeName);

    // Invoke the method itself. The string returned by the method winds up in s.
    // Note that stringParam is passed via the last parameter of InvokeMember,
    // as an array of Objects.
    String s = (String)calledType.InvokeMember(
                    methodName,
                    BindingFlags.InvokeMethod | BindingFlags.Public | 
                        BindingFlags.Static,
                    null,
                    null,
                    new Object[] { stringParam });

    // Return the string that was returned by the called method.
    return s;
}

When you call this version, pass a string in parameter stringParam. InvokeStringMethod2 will pass that string on to the called method. For example:

string s = string InvokeStringMethod2("TheClass", "TheMethod", "The string to pass on");

Call a Method in Another Project and Namespace

You may have organised your code into several projects and namespaces. The version below calls a method that may sit in a different project and/or namespace than the caller. (This version assumes that the called method doesn't take parameters.)

 public static string InvokeStringMethod3(
                        string assemblyName,
                        string namespaceName,
                        string typeName,
                        string methodName)
{
    // Get the Type for the class
    Type calledType = Type.GetType(namespaceName + "." + typeName + "," + assemblyName);

    // Invoke the method itself. The string returned by the method winds up in s
    String s = (String)calledType.InvokeMember(
                    methodName,
                    BindingFlags.InvokeMethod | BindingFlags.Public | 
                        BindingFlags.Static,
                    null,
                    null,
                    null);

    // Return the string that was returned by the called method.
    return s;
}

It assumes that each project gets compiled into its own assembly, with project and assembly having the same name. This is normally the case.

Be sure to add a reference in the project that makes the call to the project that contains the called method! Otherwise, the code can't find the assembly.

When you call this version, pass in the name of the project and the namespace as well as the class name and method name. Like so:

string s = string InvokeStringMethod3
            ("TheProject", "TheNamespace", "TheClass", "TheMethod");

Learn More

When looking at the code above, you will have found that calling a method given a string with its name takes two steps:

  1. Call method GetType of class Type, to get the Type corresponding to the class that contains the method.
  2. Call method InvokeMember on the type, to actually call the method.

To learn more, search MSDN for Type.GetType, and InvokeMember.

Some of the more interesting options include calling private methods rather than public ones, and picking a particular overloaded method.

Have a Play

To experiment a bit more, get the download that comes with this article. It has a tiny Web site serving as a test bed.

The most important files in the download are listed below:

  • DynamicallyInvokeMethodGivenItsNameAsAString.sln - Double click this file to open the solution in Visual Studio
  • Default.aspx.cs - Calls the three versions shown above
  • App_Code/TypeUtils.cs - The class holding the three versions
  • App_Code/TestClass, App_Code/TestClass2 - Classes with methods to call
  • TestClass3 in project TestProject - A class in a separate project, with a different namespace

History

  • 7th August, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Matt Perdeck
Web Developer
Australia Australia
Member
Matt has over 6 years .NET and SQL Server development experience. Before getting into .Net, he worked on a number of systems, ranging from the largest ATM network in The Netherlands to embedded software in advanced Wide Area Networks and the largest ticketing web site in Australia. He has lived and worked in Australia, The Netherlands, Slovakia and Thailand.
 
He recently wrote a book, ASP.NET Performance Secrets (www.packtpub.com/asp-net-site-performance-secrets/book) in which he shows in clear and practical terms how to quickly find the biggest bottlenecks holding back the performance of your web site, and how to then remove those bottlenecks. The book deals with all environments affecting a web site - the web server, the database server and the browser.
 
Matt's blog is mattperdeck.com
 
Matt currently lives in Sydney, Australia, where he works at Readify, a high profile software consultancy.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questiononly works with Static methods?memberMember 889461427 Apr '12 - 3:14 
Converted this code to VB.NET 2010.
 
The author should point out that this code only works when the method is a Static method (C#) or a Shared method (VB).
 
I couldn't get it to work otherwise.
Generalits goodmemberLanga Manish18 Jan '10 - 18:29 
great...code
 
langa manish

Generalgood articlememberparthi intel5 Mar '09 - 0:25 
Hi Matt,
how to do the same way for the web service and web method?
Your immediate reply would be much appreciated.
 
Thank you very much dude,
QuestionNice article...but what about different parameters with different types?memberMember 22902785 Jun '08 - 18:33 
how do i cater this problem?
MethodA maybe receives only 1 param of type string but MethodB receives 2 params of type string and integer..
how to solve this?
AnswerRe: Nice article...but what about different parameters with different types?memberdudeserius23 Jun '08 - 16:12 
I built up a class for housing little helpful functions for something such as that occasion.
The following two functions will help with this. (one is for use with static methods and one is for use with methods belonging to an instance of a class.
 
To Execute a Static Method:
        /// <summary>
        /// executes a method belonging to an external namespace/project. it allows the use for any number of parameters (as objects)
        /// </summary>
        /// <param name="assembly" type="string">the project the namespace belongs to</param>
        /// <param name="namesSpace" type="string">the namespace for which to find the class and method</param>
        /// <param name="typeName" type="string">the class type that the method belongs to</param>
        /// <param name="methodName" type="string">name of the method</param>
        /// <param name="parameters" type="params object[]">one or more parameters for the method you wish to call</param>
        /// <returns type="object">returns an object if it has anything to return</returns>
        public static object execStaticString(string assembly, string nameSpace, string typeName, string methodName, params object[] parameters)
        {
 
            //get the type of the class
            Type theType = Type.GetType(nameSpace + "." + typeName + "," + assembly);
 
            //invoke the method from the string. if there is anything to return, it returns to obj.
            object obj = theType.InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, parameters);
 
            //return the object if it exists
            return obj;
 
        }//end static object execExtString(string,string,string,string,params object[])
 
To call the above function for MethodA, you would do something like:
execStaticString("theAssembly", "theNamespace", "theClass", "MethodA", param1);
 
To call the above function for MethodB, you would do something like:
execStaticString("theAssembly", "theNamespace", "theClass", "MethodB", param1, param2);
 

 
To Execute a Non-Static Method:
        /// <summary>
        /// executes a method belonging to an external namespace/project. it allows the use for any number of parameters (as objects)
        /// </summary>
        /// <param name="classObject" type="object">the class instantiation that the method belongs to</param>
        /// <param name="methodName" type="string">name of the method</param>
        /// <param name="parameters" type="params object[]">one or more parameters for the method you wish to call</param>
        /// <returns type="object">returns an object if it has anything to return</returns>
        public static object execExtString(object classObject, string methodName, params object[] parameters)
        {
            //invoke the method from the string. if there is anything to return, it returns to obj.
            object obj = classObject.GetType().InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, classObject, parameters);
 
            //return the object
            return obj;
 
        }//end static object execExtString(string,string,string,string,params object[])
 
To call the above function for MethodA, you would do something like:
execExtString(this, "MethodA", "testing...1,2,3");
 
To call the above function for MethodB, you would do something like:
execExtString(this, "MethodB", "testing...1,2,3", 456);
 
----------------------
Nathan VanBuskirk
C++, C# Developer
http://Seriussoft.com
GeneralRe: Nice article...but what about different parameters with different types?memberGodwin Sam Josh5 Sep '08 - 9:30 
Many Thanks for that piece of code
 
Godwin

GeneralRe: Nice article...but what about different parameters with different types?memberdudeserius15 Dec '08 - 23:07 
Glad to be of some help. Smile | :)
 
----------------------------
Nathan VanBuskirk
C++, C# Developer
http://Seriussoft.com

GeneralRe: Nice article...but what about different parameters with different types?memberGenesis20019 Apr '10 - 8:10 
I was going to suggest using a params array of type object[], as well.
 
Also,
 
dudeserius wrote:
Type theType = Type.GetType(nameSpace + "." + typeName + "," + assembly);

 
String.Format that please. Adding strings together like that would create multiple string objects whereas a String.Format would create one and simply combine then together.
 
Another alternative would be:
 
Type theType = Type.GetType(String.Join(".", new string[] { nameSpace, typeName }));
 
Or, String.Format:
Type theType = Type.GetType(String.Format("{0}.{1}, {2}", nameSpace, typeName, assembly));
Thanks,
-Zack

GeneralRe: Nice article...but what about different parameters with different types?membermdelgert@hotmail.com4 Jun '12 - 12:11 
I added the following two mods for these cases mentioned approve to share. Great example.
 
using System;
using System.Linq;
using System.Reflection;
 
namespace BLL
{
 
    public class TypeUtils
    {
 
        /// ///////////////////// InvokeStringMethod //////////////////////
        ///
        /// <summary>
        /// Calls a static public method. 
        /// Assumes that the method returns a string, and doesn't have parameters.
        /// </summary>
        /// <param name="typeName">name of the class in which the method lives.</param>
        /// <param name="methodName">name of the method itself.</param>
        /// <returns>the string returned by the called method.</returns>
        /// 
        public static string InvokeStringMethod(string typeName, string methodName)
        {
            // Get the Type for the class
            Type calledType = Type.GetType(typeName);
 
            // Invoke the method itself. The string returned by the method winds up in s
            String s = (String)calledType.InvokeMember(
                            methodName,
                            BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
                            null,
                            null,
                            null);
 
            // Return the string that was returned by the called method.
            return s;
        }
 
        /// ///////////////////// InvokeStringMethod2 //////////////////////
        ///
        /// <summary>
        /// Calls a static public method. 
        /// Assumes that the method returns a string, and takes a string parameter.
        /// </summary>
        /// <param name="typeName">name of the class in which the method lives.</param>
        /// <param name="methodName">name of the method itself.</param>
        /// <param name="stringParam">parameter passed to the method.</param>
        /// <returns>the string returned by the called method.</returns>
        /// 
        public static string InvokeStringMethod2(string typeName, string methodName, string stringParam)
        {
            // Get the Type for the class
            Type calledType = Type.GetType(typeName);
 
            // Invoke the method itself. The string returned by the method winds up in s.
            // Note that stringParam is passed via the last parameter of InvokeMember,
            // as an array of Objects.
            String s = (String)calledType.InvokeMember(
                            methodName,
                            BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
                            null,
                            null,
                            new Object[] { stringParam });
 
            // Return the string that was returned by the called method.
            return s;
        }
 
        /// ///////////////////// InvokeStringMethod3 //////////////////////
        ///
        /// <summary>
        /// Calls a static public method. 
        /// Assumes that the method returns a string, and doesn't have parameters.
        /// </summary>
        /// <param name="assemblyName">name of the assembly containing the class in which the method lives.</param>
        /// <param name="namespaceName">namespace of the class.</param>
        /// <param name="typeName">name of the class in which the method lives.</param>
        /// <param name="methodName">name of the method itself.</param>
        /// <returns>the string returned by the called method.</returns>
        /// 
        public static string InvokeStringMethod3(string assemblyName, string namespaceName, string typeName, string methodName)
        {
            // Get the Type for the class
            Type calledType = Type.GetType(String.Format("{0}.{1},{2}", namespaceName, typeName, assemblyName));
 
            // Invoke the method itself. The string returned by the method winds up in s
            String s = (String)calledType.InvokeMember(
                            methodName,
                            BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
                            null,
                            null,
                            null);
 
            // Return the string that was returned by the called method.
            return s;
        }
 
        #region AddedSection
        //Added functions by Matthew David Elgert - mdelgert@yahoo.com
        /// ///////////////////// InvokeStringMethod4 //////////////////////
        ///
        /// <summary>
        /// Calls a static public method. 
        /// Assumes that the method returns a string, and doesn't have parameters.
        /// </summary>
        /// <param name="assemblyName">name of the assembly containing the class in which the method lives.</param>
        /// <param name="namespaceName">namespace of the class.</param>
        /// <param name="typeName">name of the class in which the method lives.</param>
        /// <param name="methodName">name of the method itself.</param>
        /// /// <param name="stringParam">parameter passed to the method.</param>
        /// <returns>the string returned by the called method.</returns>
        /// 
        public static string InvokeStringMethod4(string assemblyName, string namespaceName, string typeName, string methodName, string stringParam)
        {
            // Get the Type for the class
            Type calledType = Type.GetType(String.Format("{0}.{1},{2}", namespaceName, typeName, assemblyName));
 
            // Invoke the method itself. The string returned by the method winds up in s.
            // Note that stringParam is passed via the last parameter of InvokeMember, as an array of Objects.
            String s = (String)calledType.InvokeMember(
                            methodName,
                            BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
                            null,
                            null,
                            new Object[] { stringParam });
 
            // Return the string that was returned by the called method.
            return s;
        }
 
        /// ///////////////////// InvokeStringMethod5 //////////////////////
        ///
        /// <summary>
        /// Calls a static public method. 
        /// Assumes that the method returns a string
        /// </summary>
        /// <param name="assemblyName">name of the assembly containing the class in which the method lives.</param>
        /// <param name="namespaceName">namespace of the class.</param>
        /// <param name="typeName">name of the class in which the method lives.</param>
        /// <param name="methodName">name of the method itself.</param>
        /// <param name="stringParam">parameter passed to the method.</param>
        /// <returns>the string returned by the called method.</returns>
        /// 
        public static string InvokeStringMethod5(string assemblyName, string namespaceName, string typeName, string methodName, string stringParam)
        {
            //This method was created incase Method has params with default values. If has params will return error and not find function
            //This method will choice and is the preffered method for invoking 
            
            // Get the Type for the class
            Type calledType = Type.GetType(String.Format("{0}.{1},{2}", namespaceName, typeName, assemblyName));
            String s = null;
 
            // Invoke the method itself. The string returned by the method winds up in s.
            // Note that stringParam is passed via the last parameter of InvokeMember, as an array of Objects.
 
            if (MethodHasParams(assemblyName, namespaceName, typeName, methodName))
            {
                s = (String)calledType.InvokeMember(
                            methodName,
                            BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
                            null,
                            null,
                            new Object[] { stringParam });
            }
            else
            {
                s = (String)calledType.InvokeMember(
                methodName,
                BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
                null,
                null,
                null);
            }
            
            // Return the string that was returned by the called method.
            return s;
 
        }
 
        public static bool MethodHasParams(string assemblyName, string namespaceName, string typeName, string methodName)
        {
            bool HasParams;
            string name = String.Format("{0}.{1},{2}", namespaceName, typeName, assemblyName);
            Type calledType = Type.GetType(name);
            MethodInfo methodInfo = calledType.GetMethod(methodName);
            ParameterInfo[] parameters = methodInfo.GetParameters();
            
            if (parameters.Length > 0)
            {
                HasParams = true;
            }
            else
            {
                HasParams = false;
            }
 
            return HasParams;
 
        }
 
        #endregion
 
    }
 
}

QuestionHowabout dynamic execution of a method in the current class instance?memberastanton197819 Mar '08 - 5:00 
Say I have Class A and it has 2 properties (Prop1 and Prop2) and 2 methods (DoThis, DoThat).
If I have create an instance of A (objA) and then set

Prop1 = "a"
Prop2 = "b"

 
and the methods are defined as follows

Public Sub DoThis()
Prop1 += "c"
End Sub
 
Public Sub DoThat()
Prop2 += "2"
End Sub

 
If I want to have ClassA dynamically invoke DoThis() using the method you outlined (via reflection) It will create a new instance of ClassA (objB) and invoke the method. You will get a null ref exception, because objA.Prop1 will not be accessible by objB. This example is oversimplified, but think in the case of ASP.NET. If I want to access a method that is on the same page, I can, but I will not have access to any of the original pages methods and properties (all the web form control values). I can add parameters to the dynamically executed method so I have some kind of workaround, but do you know how I can best get around this?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 7 Aug 2007
Article Copyright 2007 by Matt Perdeck
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid