如何从StackTrace中检测自定义IAAttr属性?
问题
我为方法创建了自定义属性IAAttr,用于判断实例是否是作为特定方法的参数而创建的。在对象构造函数中,我通过StackTrace遍历栈帧,试图检测该自定义属性,但目前仅能捕获调试过程中生成的System.Diagnostics.DebuggerStepThroughAttribute和System.Diagnostics.DebuggerHiddenAttribute,尝试的两种检测代码均无法匹配到IAAttr(返回null或无匹配),请问应编写何种代码来正确检测栈帧中的自定义IAAttr属性?
相关代码
自定义属性定义
[System.AttributeUsage(System.AttributeTargets.Method)] public class IAAttr: System.Attribute { public string desc { get; } public IAAttr(string t) => desc = t; }
标记了自定义属性的方法
[IAAttr("instance_add")] public void instance_add(params Object[] instances) { //Do something... }
对象构造函数中的栈帧遍历代码
//[Object's constructor] StackTrace st = new StackTrace(); for (int i=1; i<DEPTH; i=i+1) { if (st.GetFrame(i).GetMethod().CustomAttributes.Count() > 0) { //if custom attribute exists, do not execute below return; } } Create();
失败的尝试代码
尝试1
st.GetFrame(i).GetMethod().GetCustomAttributes(typeof(IAAttr), true).FirstOrDefault(); //->null
尝试2
foreach (Attribute attr in st.GetFrame(i).GetMethod().GetCustomAttributes()) { if ((Type)attr.TypeId == typeof(IAAttr)) { //仅捕获到调试相关属性 } }
解决方案
问题出在StackTrace获取的方法信息是轻量级反射对象,默认不会加载自定义属性的完整元数据,导致常规的属性检测方法失效。以下是两种可靠的修正方案:
方案1:使用泛型方法精准获取(推荐)
利用MethodInfo.GetCustomAttribute<T>泛型方法直接获取目标属性,该方法会自动处理元数据加载:
// 替换构造函数循环内的检测逻辑 var targetMethod = st.GetFrame(i).GetMethod(); var iaAttr = targetMethod.GetCustomAttribute<IAAttr>(inherit: true); if (iaAttr != null) { // 检测到自定义属性,执行对应逻辑 return; }
方案2:通过类型全名匹配(兼容旧框架)
如果需要兼容.NET Framework早期版本,可以通过属性类型的全名进行匹配,避免反射类型加载差异导致的失败:
var targetMethod = st.GetFrame(i).GetMethod(); foreach (var attrData in targetMethod.CustomAttributes) { if (attrData.AttributeType.FullName == typeof(IAAttr).FullName) { // 匹配到目标属性 return; } }
额外注意点
- 确认
DEPTH的取值足够覆盖到instance_add方法所在的栈帧层级,避免因层级不足漏掉目标方法。 - 发布模式下JIT编译器的优化(比如方法内联)可能会破坏栈帧结构,可在
instance_add方法上添加[MethodImpl(MethodImplOptions.NoInlining)]特性,或者在项目设置中关闭“优化代码”选项,保证栈帧能被正确捕获。
内容的提问来源于stack exchange,提问作者DaybreakFlower
相关产品推荐
相关产品推荐

