如何使用Reflection来调用一个在C#中将字符串数组作为参数的方法

时间:2012-03-07 15:45:57

标签: c# arrays reflection parameters system.reflection

我有一个如下所示的方法......

public bool MakeRequest(string[] args)
    {
        try
        {
            sXmlRequest = args[0];
            sResponse = "";
            Console.WriteLine(sXmlRequest);
            sw.Write(sXmlRequest);
            sw.Flush();
            sResponse = sr.ReadToEnd();
            return true;
        }
        catch (Exception e)
        {
            sResponse = e.Message;
            return false;
        }

    }

我必须使用Reflection调用此方法,因为整个框架的设置方式。

以下是我用来称呼它的代码

string[] innerargs = {"Dummy Args"};
string pAssembly = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\TCPConnector.dll";
Assembly assemblyInstance = Assembly.LoadFrom(pAssembly);
Type tConnector = assemblyInstance.GetType("Fit.TcpConnector");
Object oLateBound = assemblyInstance.CreateInstance(tConnector.FullName);

result = tConnector.InvokeMember("MakeRequest", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, oLateBound, innerargs);

这回复了MissingMethodException,说找不到方法Fit.TcpConnector.MakeRequest。

但是,如果我将MakeRequest的签名更改为

  public bool MakeRequest(string args)

而不是

  public bool MakeRequest(string[] args)

然后,它正在发挥作用。在调用以数组为参数的函数时,有人能指出正确的方向吗?

5 个答案:

答案 0 :(得分:6)

C#支持元素类型为引用类型的数组上的数组元素类型协方差。也就是说,您可以自动将string[]转换为object[]

所以这里发生的是你传递一个字符串数组,运行时说“啊,那是我期待的对象数组”,现在每个字符串都作为参数传递 ,而不是将字符串数组作为参数传递。

诀窍是创建包含字符串数组的对象数组,而不是字符串数组相同的对象数组。

答案 1 :(得分:5)

你必须传递一个包含你的数组的数组:

tConnector.InvokeMember(
    "MakeRequest",
    BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
    null, oLateBound, new object[] { innerargs });

那是因为传递给方法的数组中的每个项代表函数的一个参数。由于您的函数有一个string[]类型的参数,因此您需要为其提供一个包含string[]类型项的数组。

话虽如此,我认为使用GetMethod()Invoke()InvokeMember()更清晰:

var makeRequestMethod = tConnector.GetMethod("MakeRequest");
makeRequestMethod.Invoke(oLateBound, new object[] { innerargs });

正如Eric Lippert在答案中指出的那样,你的错误代码是由于数组协方差而编译的。

答案 2 :(得分:4)

您只需将字符串参数放入object - 数组。

new Object[] { new String[] { "Mytext" } }

您需要执行此操作的原因是InvokeMemberobject - 数组作为参数,因此您的字符串数组将转换为对象数组,并且每个字符串都会作为单个数据进行威胁参数。

答案 3 :(得分:1)

你的innerargs值是错误的。

在innerargs数组中,每个对象代表一个参数

所以你真的要做

string[] innerargs = {"Dummy Args"};

object[] arg = {innerargs];

result = tConnector.InvokeMember("MakeRequest", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, oLateBound, arg );

或者某些人。

答案 4 :(得分:1)

args参数是一个传递给成员的参数数组,所以如果你的成员参数是一个数组,你需要将它包装在另一个数组中,否则它假设你只是发送一个字符串参数:

result = tConnector.InvokeMember("MakeRequest", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, oLateBound, new object[] { innerargs });