Почему я не могу получить значение для параметров типа out или ref, используя Type.InvokeMember?
Длинное название, но я хотел, чтобы оно было конкретным. Название действительно вопрос. Хотя метод, который InvokeMember
звонит имеет out
параметр и присваивает значение этому параметру, я не могу получить это значение. Вот код, который я изначально использовал:
string parameter = "";
int result = Convert.ToInt32(typeof(Ability).InvokeMember(selectedMove, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { parameter }));
Я изменил это так, что теперь заставляет его работать как задумано, но я не знаю почему:
object[] args = new object[1]; //necessary to retrieve ref/out parameter
int result = Convert.ToInt32(typeof(Ability).InvokeMember(selectedMove, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, args));
3 ответа
В вашем первом примере кода, вызов InvokeMember
не меняет значение parameter
переменная, он просто заменяет первый элемент в массиве параметров (который теперь указывает на другой string
пример). Поскольку вы не сохранили ссылку на этот массив, вы не можете получить значение выходного параметра.
Другими словами: массив изначально содержит копию parameter
переменная (т.е. копия ссылки на пустую строку). После звонка parameter
и значение в массиве ссылается на 2 разных экземпляра строки.
Я просто хотел помочь кому-то, кто борется (я сделал) с неуправляемым (COM) и возвращением ref-параметра. Таким образом, при использовании InvokeMember против COM-метода вы должны указать, какие аргументы относятся к типу ref. Это достигается с помощью ParameterModifier-class, например:
object[] args = new object[3] { param1, param2, errorStr };
ParameterModifier pMod = new ParameterModifier(3);
pMod[2] = true;
ParameterModifier[] mods = { pMod };
object tempObj = myCOMObject.GetType().InvokeMember("MyCOMMethod", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public, null, myCOMObject, args, mods, null, null);
В приведенном выше коде третий аргумент устанавливается как ссылка (pMod[2] = true;)
В вашем втором фрагменте отсутствует довольно важная строка кода. Это должно выглядеть так, предполагая, что аргумент out имеет тип string:
object[] args = new object[1]; //necessary to retrieve ref/out parameter
int result = Convert.ToInt32(typeof(Ability).InvokeMember(selectedMove,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null, null, args));
string outValue = (string)args[0]; // <=== here!
Теперь также должно быть очевидно, почему ваш первый фрагмент не может работать, у вас нет ссылки на массив object[], который вы передаете, поэтому вы никогда не сможете получить измененный аргумент.