为什么方法调用会因参数异常而失败?
Why does Method Invoke fail with argument exception?
考虑来自 WinForms 应用程序的代码示例:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
object[] parms = new object[1];
parms[0] = "foo";
DoSomething(parms);
}
public static string DoSomething(object[] parms)
{
Console.WriteLine("Something good happened");
return null;
}
}
它按预期工作,当您单击 button1 时,它会在控制台上打印 "Something good happened"。
现在考虑这个代码示例,它除了使用反射调用 DoSomething
之外是相同的:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
object[] parms = new object[1];
parms[0] = "foo";
System.Reflection.MethodInfo mi = typeof(Form1).GetMethod("DoSomething");
mi.Invoke(null, parms);
}
public static string DoSomething(object[] parms)
{
Console.WriteLine("Something good happened");
return null;
}
}
它在行 mi.Invoke(null, parms)
上抛出一个 System.ArgumentException
(类型 'System.String' 的对象无法转换为类型 'System.Object[]'。)
parms 显然是一个对象数组,而 DoSomething 的方法签名显然需要一个对象数组。那么为什么 invoke 将第一个对象从数组中拉出并试图传递它呢?
或者是其他我不理解的事情发生了?
object[] parms = new object[1];
parms[0] = "foo";
与:
public static string DoSomething(object[] parms)
这就是问题所在;第一个参数不是 string
- 它是 object[]
。您传递给 Invoke
的 object[]
依次表示 每个参数 ,因此长度为 1 的 object[]
与字符串将匹配 static string DoSomething(string s)
,但与您的方法不符。要么更改签名,要么包装值。坦率地说,我建议在这里更改签名是更好的主意,但是:
parms[0] = new object[] { "foo" };
也可以
MethodInfo.Invoke
需要一个对象数组,其中对象数组中的每个对象对应于方法 的一个参数。对象数组中的第一个参数是第一个参数,数组中的第二个对象是第二个方法,等等
由于您希望方法的第一个参数是 object[]
,因此您需要确保传递给 MethodInfo.Invoke
的对象数组中的第一个对象是表示 DoSomething
应该使用的数组的对象数组 。
MethodInfo.Invoke
期望一个对象数组作为参数将多个参数传递给函数,数组中的每个对象将是一个不同的参数。
由于您的函数还需要一个对象数组,您作为参数传递的不是对象数组而是字符串。
您必须将该数组包装到另一个数组中,这样 Invoke 将打开第一个数组并将内部数组用作调用的第一个参数。
mi.Invoke(null, new object[]{ parms });
parms is clearly an object array, and DoSomething's method signature is clearly expecting an object array.
是的,它需要一个对象数组。但是当你通过这个时:
object[] parms = new object[1];
你说这些是 DoSomething
的参数,所以 parms[0] 是 DoSomething
的第一个参数,如果 parms
中有更多项目,那么 parms[1]将是第二个参数,依此类推。
很明显 DoSomething
的第一个参数不是 string
(parms[0]) 所以你得到这个错误:
It throws an System.ArgumentException on the line mi.Invoke(null, parms) (Object of type 'System.String' cannot be converted to type 'System.Object[]'.)
考虑来自 WinForms 应用程序的代码示例:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
object[] parms = new object[1];
parms[0] = "foo";
DoSomething(parms);
}
public static string DoSomething(object[] parms)
{
Console.WriteLine("Something good happened");
return null;
}
}
它按预期工作,当您单击 button1 时,它会在控制台上打印 "Something good happened"。
现在考虑这个代码示例,它除了使用反射调用 DoSomething
之外是相同的:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
object[] parms = new object[1];
parms[0] = "foo";
System.Reflection.MethodInfo mi = typeof(Form1).GetMethod("DoSomething");
mi.Invoke(null, parms);
}
public static string DoSomething(object[] parms)
{
Console.WriteLine("Something good happened");
return null;
}
}
它在行 mi.Invoke(null, parms)
上抛出一个 System.ArgumentException
(类型 'System.String' 的对象无法转换为类型 'System.Object[]'。)
parms 显然是一个对象数组,而 DoSomething 的方法签名显然需要一个对象数组。那么为什么 invoke 将第一个对象从数组中拉出并试图传递它呢?
或者是其他我不理解的事情发生了?
object[] parms = new object[1];
parms[0] = "foo";
与:
public static string DoSomething(object[] parms)
这就是问题所在;第一个参数不是 string
- 它是 object[]
。您传递给 Invoke
的 object[]
依次表示 每个参数 ,因此长度为 1 的 object[]
与字符串将匹配 static string DoSomething(string s)
,但与您的方法不符。要么更改签名,要么包装值。坦率地说,我建议在这里更改签名是更好的主意,但是:
parms[0] = new object[] { "foo" };
也可以
MethodInfo.Invoke
需要一个对象数组,其中对象数组中的每个对象对应于方法 的一个参数。对象数组中的第一个参数是第一个参数,数组中的第二个对象是第二个方法,等等
由于您希望方法的第一个参数是 object[]
,因此您需要确保传递给 MethodInfo.Invoke
的对象数组中的第一个对象是表示 DoSomething
应该使用的数组的对象数组 。
MethodInfo.Invoke
期望一个对象数组作为参数将多个参数传递给函数,数组中的每个对象将是一个不同的参数。
由于您的函数还需要一个对象数组,您作为参数传递的不是对象数组而是字符串。
您必须将该数组包装到另一个数组中,这样 Invoke 将打开第一个数组并将内部数组用作调用的第一个参数。
mi.Invoke(null, new object[]{ parms });
parms is clearly an object array, and DoSomething's method signature is clearly expecting an object array.
是的,它需要一个对象数组。但是当你通过这个时:
object[] parms = new object[1];
你说这些是 DoSomething
的参数,所以 parms[0] 是 DoSomething
的第一个参数,如果 parms
中有更多项目,那么 parms[1]将是第二个参数,依此类推。
很明显 DoSomething
的第一个参数不是 string
(parms[0]) 所以你得到这个错误:
It throws an System.ArgumentException on the line mi.Invoke(null, parms) (Object of type 'System.String' cannot be converted to type 'System.Object[]'.)