Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何获取调用方法的参数值? 问题:_C#_Reflection_Dynamic - Fatal编程技术网

C# 如何获取调用方法的参数值? 问题:

C# 如何获取调用方法的参数值? 问题:,c#,reflection,dynamic,C#,Reflection,Dynamic,我正在编写一些代码,需要能够从调用类的方法中获取参数的值。我知道如何获取ParameterInfo[]数组,但不知道如何获取值。这可能吗 如果是,我认为这与使用MethodInfo对象中的MethodBody属性有关,它允许您检查IL流,包括属性,但我不知道如何操作,而且我还没有在Google上找到适用的代码 代码 //从调用该类的类中查找调用方法 公共类 { 公共静态void FindMethod() { 对于(int i=1;i

我正在编写一些代码,需要能够从调用类的方法中获取参数的值。我知道如何获取ParameterInfo[]数组,但不知道如何获取值。这可能吗

如果是,我认为这与使用MethodInfo对象中的MethodBody属性有关,它允许您检查IL流,包括属性,但我不知道如何操作,而且我还没有在Google上找到适用的代码

代码
//从调用该类的类中查找调用方法
公共类
{
公共静态void FindMethod()
{
对于(int i=1;i
您不能使用StackFrame或StackTrace。但是,您可以使用一些拦截框架(例如Spring.NET中的AOP内容),以便掌握参数值。

微软的Jonathan Keljo在中说:

不幸的是,从数据库中获取参数信息的唯一简单方法 今天的callstack带有调试器。如果你想做这件事 在应用程序中记录错误,并且您计划将错误日志发送回 你的支持部门,我们希望你能使用迷你转储 未来的目标。(如今,将小型转储与托管代码一起使用是一个很好的选择。) 问题不大,因为它没有包含足够的信息,甚至无法获取 默认情况下堆栈跟踪。带堆的小型转储更好,但不是“小型” 如果你知道我的意思。)

纯粹主义者会说,允许人们编写能够 调用堆栈上其他函数的参数会鼓励它们 打破封装,创建代码,这是非常脆弱的面对 改变(您的场景没有这个特殊问题,但我 听到其他人对这项功能的要求,不管怎样,大多数人 请求可以通过其他方式解决,比如使用线程存储。)但是, 更重要的是,这会对应用程序的安全性产生影响 如果允许使用插件,那么这些插件就有可能会在短时间内刮掉堆栈 敏感信息。我们当然可以将该功能标记为需要 完全信任,但这将使它在几乎所有情况下都无法使用 我听说过

乔纳森


所以。。。我猜简短的回答是“我不能”。这太糟糕了。

如果你不自己反省堆栈,你就无法做到这一点(这是很脆弱的,因为许多优化可能意味着堆栈框架不是你所期望的,甚至传递的参数实际上也不是方法签名所建议的(优化JIT编译器完全有可能发现您只使用了对象/结构的子字段并传递它)

ParameterInfo只是告诉您编译后的方法的签名,而不是传递的值

自动实现这一点的唯一现实方法是通过代码注入(通过类似AOP的方式)来创建数据,并在分析IL的基础上对其进行处理

这通常不是一个好主意,如果您需要调试某些东西,请使用调试器;如果您需要记录某些东西,请明确说明您所记录的内容

清楚地说,简单的反射技术无法以完全的通用性实现您的愿望

请参见此处:

根据我答案中的所有注释,我认为这是不可能的。PropertyInfo类确实有一个GetValue方法,但这要求您拥有一个实际的对象,您希望从中获取值。

是的,您可以这样做

您需要做的是使用IL反汇编程序(可在System.Reflection.Emit命名空间中实现)查找包含您要查找的参数值的操作数

从这个问题开始:

然后使用答案中提到的课程(来自Mono.Reflection)进行检查。类似如下:

            var instructions = method.GetInstructions();
            foreach (var instruction in instructions)
            {
                var methodInfo = instruction.Operand as MethodInfo;
                if(methodInfo == null)
                {
                    continue;
                }
                if (instruction.OpCode.Name.Equals("call") && methodInfo.Name.Equals("YourMethodHere"))
                {
                    var value = (CastToMyType)instruction.Previous.Operand;
                    // Now you have the value...
                }
            }

不确定这算不算解决方案,但我在一个具体案例中工作过, 我想在每次修改一个浮点数时记录代码的变化

读取堆栈跟踪行上的文件以确定参数

public static Score operator +(Score x,float y) {
    var st = new StackTrace(true);
    var sf = st.GetFrame(1);                
    string paramName = File.ReadLines(sf.GetFileName()).ElementAtOrDefault(sf.GetFileLineNumber()-1).Split(new[] { "+=" }, StringSplitOptions.None)[1];
            
    x.DebugString += (paramName+" "+y);
    x.DebugString += System.Environment.NewLine;
            
    x.val += y;
    return x;
}
            
            
void Main(){
    Score score = new Score();
    float firstScore = 2;
    float secondScore = -13;
    score+=firstScore;
    score+=secondScore;
    Console.WriteLine(score.DebugString);
}
        
Output : 
firstscore  2
secondScore -13

是的,您可以使用PostSharp PostSharp.Aspects.MethodInterceptionSpect解决方案进行解释:我没有从这最后一行代码中获取值。我获取了类似构造函数信息的内容?这段代码是否有小问题?您测试过吗?
public static Score operator +(Score x,float y) {
    var st = new StackTrace(true);
    var sf = st.GetFrame(1);                
    string paramName = File.ReadLines(sf.GetFileName()).ElementAtOrDefault(sf.GetFileLineNumber()-1).Split(new[] { "+=" }, StringSplitOptions.None)[1];
            
    x.DebugString += (paramName+" "+y);
    x.DebugString += System.Environment.NewLine;
            
    x.val += y;
    return x;
}
            
            
void Main(){
    Score score = new Score();
    float firstScore = 2;
    float secondScore = -13;
    score+=firstScore;
    score+=secondScore;
    Console.WriteLine(score.DebugString);
}
        
Output : 
firstscore  2
secondScore -13