调用ListBox中选择的方法

本文关键字:方法 选择 ListBox 调用 | 更新日期: 2023-09-27 18:19:34

我正在创建的Windows窗体应用程序出现问题。该应用程序应该是一个集成测试应用程序。从本质上讲,它应该测试在我的一个类中使用大量web服务的方法。我正在通过反射从我想要测试的类中加载方法,并且这样做:

private List<string> GetMethods(Type type)
{
    return (from method in type.GetMethods() where method.IsPublic &&
        method.ReturnType == typeof(void) select method.Name).ToList();
}

这将返回该类中为测试web服务而创建的方法的列表,并将它们放在ListBox中,用户可以在其中选择他/她喜欢的任意多个方法。我的困惑来自这里。我想做的是获得用户选择的方法,并执行相应的方法X次(表单上还有一个文本框,用于输入执行方法的次数)。根据我通过反射得到的方法的名称,我不知道如何执行这些方法。我试过这样的东西,但我知道它不对:

private void RunMethods(Type type)
{
    var tester = new ClassToTest();
    foreach(var item in lstMethodList.SelectedItems)
    {
        foreach(var method in type.GetMethods())
        {
            if(String.Equals(item.ToString(), method.Name))
            {
                ThreadStart ts = new ThreadStart(method.Name);
                Thread thread1 = new Thread(ts);
                thread1.Start();
            }
         }
     }
}

这甚至不会编译,因为ThreadStart需要一个方法名作为参数。有什么办法可以做到这一点吗?也许我的逻辑是错误的,但我想为每个需要运行的方法创建一个线程,并执行该方法,无论用户指定多少次。这应该是进行集成测试和一些负载测试的一种方式,以查看web服务可以处理什么。

调用ListBox中选择的方法

您可以使用类似的方法来获得您想要的方法:

private List<MethodInfo> GetMethods(Type type)
{
        return (from method in type.GetMethods()
                where method.IsPublic &&
                    method.ReturnType == typeof(void)
                select method).ToList();
}

然后,如果你想在单独的线程中调用方法,你会写(只有在方法是静态的情况下才能工作):

foreach(MethodInfo mi in GetMethods(SomeType) {
   MethodInfo tempMi = mi;
   Action myAction = (Action) Delegate.CreateDelegate(typeof(Action), tempMi);
   ThreadStart ts = new ThreadStart(myAction);
   Thread thread1 = new Thread(ts);
   thread1.Start();
}

或者你会写(只有在方法严格没有参数的情况下,小心可能需要参数的继承方法!):

foreach (MethodInfo mi in GetMethods(type))
{
   MethodInfo tempMi = mi; //modified closure
   object o = Activator.CreateInstance( type );
   Action myAction = delegate() { tempMi.Invoke(o, null); };
   ThreadStart ts = new ThreadStart(myAction);
   Thread thread1 = new Thread(ts);
   thread1.Start();
}

如果方法采用参数,则必须相应地传递对象数组(object [] { ... }),而不是null(在当前MethodInfo上调用的Invoke方法中);with当然会校正数组中的对象。

实际上,如果你取一个线程列表,并为列表中的每个MethodInfo添加一个新的线程,这样你就可以在之后控制它们(就像你想停止一个一样),那会更好。HashMap也是一个不错的选择,键是MethodInfo或Action,值是关联的Thread。

您可以使用Activator创建类的实例。

然后可以使用Invoke调用它的一个方法。

像这样的东西应该起作用:

private void RunMethods(Type type)
{
    foreach( var item in lstMethodList.SelectedItems )
    {
        foreach( var method in type.GetMethods() )
        {
            if( String.Equals( item.ToString(), method.Name))
            {
                MethodInfo capturedMethod = method;
                var t = new Thread( () => ThreadMain( type, capturedMethod ) );
                t.Start();
            }
         }
     }
}
static void ThreadMain( Type type, MethodInfo mi )
{
    object o = Activator.CreateInstance( type );
    object[] parameters = new object[] { };
    mi.Invoke( o, parameters );
}

我假设正在测试的类有一个无参数构造函数。

您可以实现一个包含MethodInfos和Method名称的私有字典。

private Dictionary<string, MethodInfo> methodList;
        private List<string> GetMethods(Type type)
        {
            methodList = new Dictionary<string, MethodInfo>();
            type.GetMethods().Where(m=>m.IsPublic && m.ReturnType.Equals(typeof(void))).ToList().ForEach(m=>
                methodList.Add(m.Name,m)
                );
            return methodList.Keys.Select(k => k).ToList();
        }

在选择下拉列表时,您可以在字典中找到方法并执行它。