运行名称作为字符串传递的方法

时间:2009-08-18 10:08:08

标签: c#

我有一个C#方法,它接受一个字符串作为参数,该字符串包含静态方法的名称,例如

"MyClass.GetData"

是否可以从字符串中传递的值运行该方法?

8 个答案:

答案 0 :(得分:12)

是的,您可以使用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");
    }
}

答案 1 :(得分:2)

是您可以使用反射来查找方法并使用适当的参数调用。

答案 2 :(得分:2)

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});
    }
}

答案 3 :(得分:1)

您可以尝试以下方式:

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

这会给你一个MethodInfo课程。从那里,您可以使用Invoke方法(使用正确的参数)。

答案 4 :(得分:1)

答案在于反思。 您可以使用反射来获取某种类型的MethodInfo。 (你必须知道它的类型),然后你可以调用它。

但是,您确定没有更好的解决方案来解决您的问题吗?为什么它作为字符串传递?

答案 5 :(得分:1)

Reflection具有您需要的基本工具,但您仍需要自己解析字符串(将其拆分为点并将其一直反映到必要的MethodInfo)。但是,您应该注意到,这种操作的性能比直接方法调用慢几倍(如果不是千分之一或更多)。可以这样做几次,但是如果你打算这么做,你应该考虑重构你的代码,这样就不需要了。

如果确实无法避免这种情况(在大多数情况下你可以),你至少可以通过缓存在某些字典中找到的MethodInfo对象来加速它。这样你就不必每次都反思。

另外,如果您不了解它们,我建议您查找delegates。这可能是你问题的答案。它几乎和直接方法调用一样快。

答案 6 :(得分:1)

在走向反思的道路之前,这就是你要做的事情,确保没有其他更好的方法来实现它。首先检查委托,因为它们可以调用在运行时设置的方法。

所以在这里你要反思:

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);
}

一些注意事项:

  • 在此示例中,您的方法必须是静态的。原因是我们没有实例化“MyClass”。可以这样做,但它需要一个没有参数的默认构造函数。看看.GetConstructor。但通常情况下,不建议动态创建类来调用方法。
  • 静态方法在我的示例中不采用任何参数。如果是,则将mi.Invoke(...)的第二个参数替换为一个对象数组:new object [2] {232,“a string”}
  • 您可以传递要在其上调用方法的对象。你有一个MyFunction参数,它接受一个'MyClass'类型的对象,你将该对象传递给mi.Invoke()调用。

答案 7 :(得分:0)

是。唯一的问题是你也需要提供类的命名空间。

哈斯似乎已经钉了很多。因为我输入了它的麻烦..这是我的版本(temp是命名空间,User是classname,Exists是一个公共静态方法。)

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 
      }