Question

I have a method as shown below...

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

    }

I have to call this method using Reflection, because of the way the entire framework is setup.

Here is the code I'm using to call it

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

This is returning me MissingMethodException saying the method Fit.TcpConnector.MakeRequest is not found.

However, if I change the signature of the MakeRequest to

  public bool MakeRequest(string args)

instead of

  public bool MakeRequest(string[] args)

then, it is working. Can anybody point me in right direction in calling the function which takes array as its parameter?

Était-ce utile?

La solution

You have to pass it an array that contains your array:

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

That's because each item in the array you pass to the method represents one parameter to the function. And since you function has one parameter of type string[], you need to give it an array that contains one item of type string[].

That being said, I think using GetMethod() and Invoke() is clearer than InvokeMember():

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

Your incorrect code compiles because of array covariance as Eric Lippert pointed out in his answer.

Autres conseils

C# supports array element type covariance on arrays where the element type is a reference type. That is, you can automatically convert string[] to object[].

So what is happening here is you are passing an array of strings, and the runtime is saying "ah, there's that array of objects I was expecting", and now each string is being passed as an argument, rather than passing the array of strings as an argument.

The trick is to make an array of objects that contains the array of strings, rather than one that is identical to the array of strings.

You simply need to put the string arguments into a object-array.

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

The reason why you need to do this is the point that InvokeMember takes a object-array as parameter, so your string array is converted into a object array and each string is threaten as a single parameter.

Your innerargs value is wrong.

In innerargs array each object represents one parameter

so you really should make

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

object[] arg = {innerargs];

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

Or somesuch.

The args argument is an array of arguments to pass to the member, so if your member argument is an array you need to wrap it in another array, otherwise it assumes you are just sending a single string argument:

result = tConnector.InvokeMember("MakeRequest", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, oLateBound, new object[] { innerargs });
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top