我在一个类中有一些代码,它爬行堆栈跟踪以查找其调用堆栈中方法的特定属性。
我注意到我的一个测试开始从自动构建失败,当时该测试总是从我的机器传递出来。当我深入研究它时,看起来有问题的代码在调试模式或发布模式下工作正常,只要你连接了调试器,但在没有调试器的发布模式下失败。
从我所看到的,我正在寻找的方法是内联,当发生这种情况时,该方法的属性就会丢失。
是这样的吗?属性是否会丢失?
这是一个重现我的问题的小应用程序:
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
namespace InliningAndAttributes
{
public class SomeClass
{
[Description("Foo")]
public void SomeMethodThatWillGetInlined()
{
SomeMethodThatWontGetInlined();
}
protected virtual void SomeMethodThatWontGetInlined()
{
var caller = FindDescribedCaller();
Console.WriteLine("Could I find description attribute? {0}", caller != null);
}
private MethodBase FindDescribedCaller()
{
var callStack = new StackTrace();
int frameIndex = 0;
while (frameIndex++ <= callStack.FrameCount)
{
Console.WriteLine("Getting frame" + frameIndex);
var currentFrame = callStack.GetFrame(frameIndex);
if (currentFrame == null)
{
continue;
}
var method = currentFrame.GetMethod();
Console.WriteLine(method.Name);
if (Attribute.IsDefined(method, typeof(DescriptionAttribute)))
{
return method;
}
}
return null;
}
}
class Program
{
static void Main(string[] args)
{
var someClass = new SomeClass();
someClass.SomeMethodThatWillGetInlined();
Console.ReadLine();
}
}
}
当我在.Net 4.5下运行此应用程序时,使用Release版本并且没有附加调试器,我得到以下输出:
Getting frame1
SomeMethodThatWontGetInlined
Getting frame2
Main
Getting frame3
Getting frame4
Could I find description attribute? False
答案 0 :(得分:6)
用户代码无法检测内联。如果它可能是一个破碎的编译器优化。优化是不可检测的(当然,除非它们利用未定义或未指定的行为)。
错误不是属性丢失。错误是您的代码依赖于运行时StackTrace
,它确实具有未指定的内容。这是一个提供尽力而为数据的调试类。内联删除堆栈帧。
您可能不应该依赖于您的方法的调用者。 (不仅因为它不起作用,而且因为它非常脆弱而且不能自我记录)。寻找其他解决方案。通过传递一个额外的参数使调用者识别自己。