Как использовать Reflection для вызова метода, который принимает массив строк в качестве аргумента в C # - PullRequest
2 голосов
/ 07 марта 2012

У меня есть метод, как показано ниже ...

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 ]

6 голосов
/ 07 марта 2012

C # поддерживает ковариацию типа элемента массива для массивов, где тип элемента является ссылочным типом.То есть вы можете автоматически конвертировать string[] в object[].

Итак, что здесь происходит, вы передаете массив строк, и среда выполнения говорит: «А, это тот массив объектов, который я ожидал», и теперь каждая строка передается какаргумент , вместо передачи массива строк в качестве аргумента.

Хитрость заключается в том, чтобы создать массив объектов, который содержит массив строк,а не тот, который идентичен массиву строк.

5 голосов
/ 07 марта 2012

Вы должны передать ему массив, содержащий ваш массив:

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

Ваш неверный код компилируется из-за ковариации массива, как указал Эрик Липперт в своем ответе.

4 голосов
/ 07 марта 2012

Вам просто нужно поместить строковые аргументы в массив object.

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

Причина, по которой вам нужно это сделать, заключается в том, что InvokeMember принимает в качестве параметра object -массив, поэтому ваш строковый массив преобразуется в массив объектов, и каждая строка представляет собой один параметр. *

1 голос
/ 07 марта 2012

Аргумент args - это массив аргументов для передачи члену, поэтому, если ваш аргумент-член является массивом, вам нужно заключить его в другой массив, в противном случае предполагается, что вы просто отправляете один строковый аргумент:

result = tConnector.InvokeMember("MakeRequest", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, oLateBound, new object[] { innerargs });
1 голос
/ 07 марта 2012

Ваше значение innerargs неверно.

В массиве innerargs каждый объект представляет один параметр

, поэтому вы действительно должны сделать

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

object[] arg = {innerargs];

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

или что-то подобное.

...