如何传递两个参数参数int和double,以便invoke方法可以工作?

时间:2013-04-10 13:35:52

标签: c# reflection

我对c sharp的反思有疑问。这是我的问题

1)使用具有不同访问者(私有,公共,受保护)的不同字段定义类MyClass以及具有不同参数集和返回类型的方法

2)定义包含方法的MyTestClass,执行以下操作:为spicified类名打印方法名,其中方法包含字符串参数,类名是字符串值。调用类的一些方法,并将参数放到方法中,参数应该从文本文件中读取(类的名称和方法的名称是方法的参数

我想在我的类中调用method5,但它需要两个参数,当我尝试得到不匹配计数参数错误时,如何传递两个参数intdouble以便invoke方法有效吗?

Inside params.txt there is

10 1.5

我希望从文本文件中读取,下面是我的完整代码,我会很感激任何想法或修改

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.IO;

class MyClass
{
    private int i;
    public double d;
    private string s;
    public bool b;
    public MyClass()
    {
        i = 1;
        d = 0.1;
        s = "1";
        b = true;
    }
    public void Method0()
    {
        Console.WriteLine("Method with no arguments, no return value.");
    }
    private int Method1(int arg0)
    {
        Console.WriteLine("The method returns int, int gets.");
        return arg0;
    }
    private double Method2(int arg0, double arg1)
    {
        Console.WriteLine("Method returns a double, taking int and double.");
        return arg1 * arg0;
    }
    public bool Method3(string arg0)
    {
        Console.WriteLine("Method returns a bool, accepts string");
        return arg0.Length>10;
    }
    public bool Method3(string arg0,string arg1)
    {
        Console.WriteLine("The method takes two arguments string.");
        return arg0 == arg1;
    }
    public static char Method4(string arg0)
    {
        Console.WriteLine("Method returns a char, accepts string. .");
        Console.WriteLine(arg0);
        return arg0[1];
    }
    public void Method5(int arg0, double arg1)
    {
        Console.WriteLine("arg1 = {0} arg2 = {1}.",arg0,arg1);
    }
}

class MyTestClass
{
    public static string[] GetMethodsWithStrParams(string className)
    {
        var t = Type.GetType(className);
        List<string> res = new List<string>();
        foreach (var method in t.GetMethods())
        {
            foreach (var param in method.GetParameters())
            {
                if (param.ParameterType == typeof(string))
                {
                    res.Add(method.Name);
                    break;
                }
            }
        }
        return res.ToArray();
    }
    public static void InvokeMethod(string className, string methodName, string fileName)
    {
        var t = Type.GetType(className);
        using (StreamReader f = new StreamReader("params.txt"))
        {
            t.GetMethod(methodName).Invoke(t.GetConstructor(Type.EmptyTypes).Invoke(new object[] { }),
                                           new object[] { f.ReadLine(), f.ReadLine()+"1" });
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        string name = "MyClass";

        foreach (var x in MyTestClass.GetMethodsWithStrParams(name))
        {
            Console.WriteLine(x);
        }

        MyTestClass.InvokeMethod("MyClass", "Method5", "params.txt");

        Console.ReadKey(true);
    }
}

2 个答案:

答案 0 :(得分:0)

由于这是您上一个问题的延续,因此以下是您需要解决的一些问题:

1)我不认为你想让params.txt只包含Method5的参数,否则当你尝试其他方法时你的应用会失败

2)您需要将文件中的行解析为对象数组。

我会做像

这样的事情

params.txt:

Method5: 1 1.5
Method4: some string
...

我建议使用tab字符作为分隔符或竖线(|)或有效参数中不需要的任何内容,否则您将无法使用包含空格的字符串。

现在,您的代码需要找到被调用方法的行,并将其拆分为多个部分以获取参数。例如。对于method5,您现在将有2个表示参数的字符串:“1”和“1.5”

接下来你需要做的是将这些字符串转换为该方法调用的正确类型的对象(即int和double)。

一种方法是将参数类型编码为params.txt:

Method5L: 1:int 1.5:float

但这很容易出错,当你改变你的方法时很容易失去同步,所以更好的方法是通过反射得到参数类型,即来自表示方法的MethodInfo对象:

var parameters = method.GetParameters();

最后一步是进行转化 - 你可以使用像int.Parsedouble.Parse这样的方法,或者甚至更好的Convert类,例如:Convert.ChangeType("1.5", typeof(float))

var args = new objects[parameters.Length]; 
var argStrings = {"1", "1.5"}; // obviously, you must get these from params.txt, not hardcode it
int idx = 0;
foreach (var param in parameters) {
    args[idx] = Convert.ChangeType(argStrings[idx], param.ParameterType);
    idx++;
}

现在,您可以通过argsInvoke数组作为参数列表提供给您的方法。

就是这样,现在你只需编码就可以了。

答案 1 :(得分:0)

您需要将文件中的所有字符串转换为方法中使用的相应类型:

using System;
using System.Linq;
using System.IO;

class MyInvokedClass
{
  public void MyInvokedMethod(int arg0, double arg1)
  {
    Console.WriteLine("arg1 = {0} arg2 = {1}.", arg0, arg1);
  }
}

class Program
{
  public static void InvokeMethod(string className, string methodName, string fileName)
  {
    string[] contents = File.ReadAllLines(fileName);

    var t = Type.GetType(className);
    var m = t.GetMethod(methodName);

    var parametertypes = m.GetParameters().Select(p => p.ParameterType);

    var parameters = parametertypes.Select((type, index) => Convert.ChangeType(contents[index], type)).ToArray();
    var instance = Activator.CreateInstance(t);

    m.Invoke(instance, parameters);
  }

  static void Main()
  {
    InvokeMethod("MyInvokedClass", "MyInvokedMethod", "params.txt");

    Console.ReadKey(true);
  }
}

该文件显示为:

42
12.34

(请注意,您可能需要将程序文化使用的小数点替换为。)