Ответ 1
ParameterInfo[] parameters = myMethodInfo.GetParameters();
foreach(ParameterInfo parameter in parameters)
{
bool isRef = parameterInfo.ParameterType.IsByRef;
}
Я не уверен, что я вообще что-то пропустил, но не могу найти способ определить, передается ли параметр по ссылке или нет, используя отражение.
В ArgumentInfo есть свойство IsOut, но нет "IsRef". Как я могу получить все ссылочные параметры в заданном MethodInfo?
ParameterInfo[] parameters = myMethodInfo.GetParameters();
foreach(ParameterInfo parameter in parameters)
{
bool isRef = parameterInfo.ParameterType.IsByRef;
}
Вам нужно еще раз изучить тип вашего параметра. Например, если у вас есть
void Foo(ref int bar)
тогда имя параметра не будет int
или Int32
(как вы могли ожидать), но вместо этого Int32&
. Для каждого типа существует корреспондент by-ref-type, где исходный тип суффикс "&".
Вы можете проверить это с помощью свойства IsByRef
класса Type
.
ParameterType.IsByRef
вернет true
для параметров ref
и out
.
Если у вас есть объект ParameterInfo
(например, от MethodInfo.GetParameters()
), то:
out
, если parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut
ref
, если parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut == false
Если вы не выполните проверку IsByRef
для параметров out
, вы неправильно получите элементы, украшенные атрибутом [Out]
из System.Runtime.InteropServices
, но не являющиеся фактически параметрами С# out
.
ParameterInfo.ParameterType.IsByRef возвращает true, если объявление параметра имеет ключевое слово ByRef и возвращает значение false, если объявление имеет ключевое слово ByVal (независимо от того, является ли тип параметра по-значению (например, структура ) или по ссылке (например, класс)).
Чтобы проиллюстрировать, рассмотрим следующую структуру и класс (я использую код VB):
' Empty structure and class, just for illustration.
Public Structure MyStruct
End Structure
Public Class MyClass1
End Class
И предположим, что у вас есть следующий метод, который принимает аргументы ByVal и ByRef для структуры и класса, определенных выше (обратите внимание, что, начиная с VB 2012, вы можете опустить ключевое слово ByVal, поскольку оно по умолчанию):
Public Sub P(s1 As MyStruct, ByRef s2 As MyStruct, c1 As MyClass1, ByRef c2 As MyClass1)
End Sub
Теперь следующий код проверяет метод ParameterInfo.ParameterType.IsByRef:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
' Reflect on method P:
Dim mi As MethodInfo = Me.GetType.GetMethod("P")
' Iterate all parameters, and call its ParameterType.IsByRef method:
For Each pi As ParameterInfo In mi.GetParameters
If **pi.ParameterType.IsByRef** _
Then Console.WriteLine(pi.Name & " is ByRef") _
Else Console.WriteLine(pi.Name & " is ByVal")
Next
End Sub
Вы получите следующий результат:
s1 is ByVal
s2 is ByRef
c1 is ByVal
c2 is ByRef
Как вы можете видеть, ParameterInfo.ParameterType.IsByRef возвращает true для аргументов s2 и c2, потому что они определены с помощью ключевого слова ByRef, хотя одна из них - это структура (тип значения), а другая - класс (ссылка -тип); и возвращает false для аргументов, определенных с помощью ключевого слова ByVal.
Обратите внимание, однако, что ключевое слово ByVal не означает, что все аргументы будут переданы как копия. Даже если это ключевое слово (ByVal) используется, если тип является ссылкой на ссылку (например, класс), аргумент будет передаваться по ссылке, как если бы использовалось ключевое слово ByRef. То есть, c1 и c2 метода P выше будут ОБА быть переданы по ссылке, а это означает, что если P изменяет поле или свойство на c1 или c2, изменения будут отражаться на вызывающем. (ByVal и ByRef делают разницу главным образом, когда тип является значением, таким как структура.)
если ref parameterInfo.IsIn == true && parameterInfo.IsOut == true
то вам может не понадобиться, если parameterInfo.ParameterType.IsByRef
вообще