Gavin
Gavin

Reputation: 17392

Run a method thats name was passed as a string

I have a C# method that takes a string as an argument, that string contains the name of a static method e.g

"MyClass.GetData"

Is it possible to run that method from the value passed in the string?

Upvotes: 5

Views: 5473

Answers (8)

Kieron
Kieron

Reputation: 27127

You could try something like:

typeof (MyClass).GetMethod (MyClass.GetData) // Assuming get data is the string name.

That would return to you a MethodInfo class. From that, you can use the Invoke method (with the right params).

Upvotes: 1

ADB
ADB

Reputation: 2329

Before going down the path of reflection, which is what you are thing to do is called, make sure that there is no other better way of implementing it. Check delegates first of all, as they can call a method that is set at runtime.

So here you go for reflection:

public void MyFunction()
{
    string dotSeparatedParams = "Myclass.Method";
    string[] arrayParams = dotSeparatedParams.Split('.');
    // since the class was defined in the string, start with loading it
    Type classType = Type.GetType(arrayParams[0]);
    if( classType == null )
        throw new Exception();
    // load the reference to the method
    MethodInfo mi = classType.GetMethod(arrayParams[1]);
    if (mi == null)
        throw new Exception();
    // call the method
    mi.Invoke(null, null);
}

A few notes:

  • In this example, your method must be static. The reason is that we are not instancing 'MyClass'. It is possible to do so, but it requires a default contructor with no parameters. Look at .GetConstructor for that. But generally, it is not advisable to create the class on the fly to call a method.
  • The static method doesn't take any parameters in my example. If it does, then replace the second argument of mi.Invoke(...) with an array of objects: new object[2] { 232, "a string" }
  • You could pass the object on which you want to call the method instead. You'd have a parameter to MyFunction that takes in an object of type 'MyClass' and you'd pass that object to the mi.Invoke() call.

Upvotes: 1

Gishu
Gishu

Reputation: 136663

Yes. Only thing is that you'd need to supply the namespace of the class as well.

Hath seems to have nailed it pretty much. Since I took the trouble of typing it out.. Here's my version (temp is the namespace, User is the classname and Exists is a public static method within it.)

private static object ExecuteStaticMethod(string method_full_path, object[] args)
      {
         var tokens = method_full_path.Split('.');
         string class_full_name = String.Format("{0}.{1}", tokens[0], tokens[1]);
         var class_blueprint = Assembly.GetExecutingAssembly().GetType(class_full_name);
         var handle_to_method = class_blueprint.GetMethod(tokens[2], BindingFlags.Default | BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public);
         return handle_to_method.Invoke(null, args);

      }

      public static void Main(string[] args)
      {
         Console.WriteLine( ExecuteStaticMethod("temp.User.Exists", new object[] {"Gishu"} ) ); // prints false
         User.Create("Gishu");
         Console.WriteLine(ExecuteStaticMethod("temp.User.Exists", new object[] { "Gishu" }));  // prints true 
      }

Upvotes: 0

Vilx-
Vilx-

Reputation: 107002

Reflection has the basic tools you need, but you will still need to parse the string yourself (split it at the dots and reflect it all the way down to the necessary MethodInfo). However you should note that the performance of such an operation is several hundread (if not thousand or more) times slower than direct method invocation. It's OK to do it a few times, but if you intend to do this a lot, you should really consider refactoring your code in such a way that this is not necessary.

If you really cannot avoid this (and in most cases you can), you can at least speed it up by caching the MethodInfo objects that you have found in some dictionary. This way you won't have to reflect every time.

Also, in case you don't know about them, I'd advise looking up delegates. Chances are that this is an answer to your problem. And it is nearly as fast as a direct method call.

Upvotes: 1

Hath
Hath

Reputation: 12779

yes you can using System.Reflection


CallStaticMethod("MainApplication.Test", "Test1");

public  static void CallStaticMethod(string typeName, string methodName)
{
    var type = Type.GetType(typeName);

    if (type != null)
    {
        var method = type.GetMethod(methodName);

        if (method != null)
        {
            method.Invoke(null, null);
        }
    }
}

public static class Test
{
    public static void Test1()
    {
        Console.WriteLine("Test invoked");
    }
}

Upvotes: 12

KV Prajapati
KV Prajapati

Reputation: 94653

Reflection API

class Test
{
    public void Print(int n)
    {
        Console.WriteLine(n);
    }
}
class MainA
{
   static void Main()
    { 
        Type t = typeof(Test);
        Object obj = new Test();
        System.Reflection.MethodInfo m = t.GetMethod("Print");
        m.Invoke(obj,new object[]{11});
    }
}

Upvotes: 2

Ashok Ralhan
Ashok Ralhan

Reputation: 21

Yes You can use reflection to find the method and invoke with proper arguements.

Upvotes: 2

Frederik Gheysels
Frederik Gheysels

Reputation: 56964

The answer lies in reflection. You can use reflection to get the MethodInfo of a certain type. (You have to know the type that is), and then you can invoke it.

But, are you sure that there is no better solution to solve your problem ? Why is it passed as a string ?

Upvotes: 1

Related Questions