Можно перечислить типы/информацию параметра вызываемого метода как это:
private void SomeMethod(int thisValue, string thatValue)
{
StackTrace stackTrace = new StackTrace();
foreach (ParameterInfo pInfo in stackTrace.GetFrame(0).GetMethod().GetParameters())
{
string name = pInfo.Name;
string type = pInfo.GetType().ToString();
}
}
Но есть ли какой-либо способ получить фактический объект каждого параметра?
Править: Моя цель состоит в том, чтобы перечислить все параметры и получить их значения. Используя Выражения LinQ, можно получить значение параметра как так:
private void SomeMethod(int thisValue, string thatValue)
{
object valueOfThis = GetParameterValue(() => thisValue);
object valueOfThat = GetParameterValue(() => thatValue);
}
private object GetParameterValue<T>(Expression<Func<T>> expr)
{
var body = ((MemberExpression)expr.Body);
return ((FieldInfo)body.Member).GetValue(((ConstantExpression)body.Expression).Value);
}
Но то, что я хотел бы сделать, является чем-то как:
foreach (fooObject o in thisMethod.GetParameterObjects())
{
object someValue = GetParameterValue(() => fooObject);
}
И, таким образом, имейте общий метод для набора все параметры и их значения.
Обновление:
Похоже, я «переодоварил» начальный ответ, пытаясь объяснить все. Вот короткая версия ответа.
private static void SomeMethod(int thisValue, string thatValue)
{
IEnumerable<object> parameters = GetParameters(() => SomeMethod(thisValue, thatValue));
foreach (var p in parameters)
Console.WriteLine(p);
}
private static IEnumerable<object> GetParameters(Expression<Action> expr)
{
var body = (MethodCallExpression)expr.Body;
foreach (MemberExpression a in body.Arguments)
{
var test = ((FieldInfo)a.Member).GetValue(((ConstantExpression)a.Expression).Value);
yield return test;
}
}
И вот длинная версия с некоторыми объяснениями.
На самом деле, если вы используете деревья выражения, вам не нужно находиться внутри метода для перечисления его параметров.
static void Main(string[] args)
{
// First approach.
IEnumerable<object> parameters = GetParametersFromConstants(() => SomeMethod(0, "zero"));
foreach (var p in parameters)
Console.WriteLine(p);
// Second approach.
int thisValue = 0;
string thatValue = "zero";
IEnumerable<object> parameters2 = GetParametersFromVariables(() => SomeMethod(thisValue, thatValue));
foreach (var p in parameters2)
Console.WriteLine(p);
Console.ReadLine();
}
private static void SomeMethod(int thisValue, string thatValue)
{
Console.WriteLine(thisValue + " " + thatValue);
}
private static IEnumerable<object> GetParametersFromVariables(Expression<Action> expr)
{
var body = (MethodCallExpression)expr.Body;
foreach (MemberExpression a in body.Arguments)
{
var test = ((FieldInfo)a.Member).GetValue(((ConstantExpression)a.Expression).Value);
yield return test;
}
}
private static IEnumerable<object> GetParametersFromConstants(Expression<Action> expr)
{
var body = (MethodCallExpression)expr.Body;
foreach (ConstantExpression a in body.Arguments)
{
var test = a.Value;
yield return test;
}
}
}
Примечание, что, если вы используете деревья выражения, ваш код очень зависит от выражения, передаваемого методу. Я показал один, использующий константы и одну с помощью переменных. Но, конечно, могут быть больше сценариев. Вы можете рефакторизоровать этот код, чтобы использовать один метод для обоих случаев, но я решил, что это иллюстрирует эту проблему таким образом.
Хорошо, так вот сделка.
Вы не можете сделать это, а не с управляемого языка. Я не вижу, как кто-то позволит вам взять под контроль кадров стека. И так, как вы хотите. Поскольку вам нужна информация, чтобы получить значения.
Теперь время выполнения знает это, он имеет всю информацию, но вы не можете сделать предположения о том, как она пойдет на создание кадра стека, потому что вы не должны делать это.
Эрго, есть только один способ поступить об этом. Профилирование API.
Я в конечном итоге здесь . В рамках функций API профилирования. Могу поспорить, что есть способ сделать это, что давайте выпариваем значения параметров, вызывая неуправляемый класс из управляемого кода.
Теперь я бы не сделал этого, потому что там уже есть большие профилирование инструментов уже, Jetbrains Dottrace для имени один и с IntelliTrace в VS2010 все эти головные боли будут просто уходить ... IntelliTrace позволит вам сделать время путешествовать по отладке.
Другой и очевидный способ сделать это абсолютно FOOBAR, но может в конечном итоге развлечься, чтобы поэкспериментировать, он всегда может быть сделан таким образом, но я бы никогда в моей жизни не поставил этот код в производственной среде.
// compile with unsafe
unsafe
{
var p = stackalloc int[1];
var baseAddr = p - sizeof(int);
}
Теперь вы не можете написать в Baseaddr
, но вам следует разрешить прочитать его. Сложная часть состоит в том, чтобы иметь смысл кадров стека, и это связано с призванной конвенцией, и что вы должны знать наверняка наверняка времени. Вот , проходящий из этого вещей, и это FastCall.
С этой информацией и объектами параметров вы сможете пройти свой путь через аргументы.
Поскольку вы будете работать с необработанными указателями, вам нужно сделать теми в управляемые объекты, и есть класс для этого.
Там вы идете, идите гайки!
Большое предупреждение, хотя , что вы найдете, как вы поднимаетесь вверх по стеку, не будут то, что вы ожидаете. Поскольку аргументы могут быть помещены в регистры и регистры не могут быть доступны из-за управляемого кода.
Вы можете использовать MethodInfo.getCurrentMethod (). GetParameters ()
, чтобы получить список параметров метода. Но невозможно получить свои ценности путем размышлений.