Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Reflection to call a method that takes a string array as argument in C#

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?

like image 710
Buddha Avatar asked Dec 01 '25 05:12

Buddha


2 Answers

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.

like image 83
Eric Lippert Avatar answered Dec 03 '25 20:12

Eric Lippert


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.

like image 22
svick Avatar answered Dec 03 '25 20:12

svick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!