You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反射调用Assembly.GetExecutingAssembly内部代码返回null的原因咨询

为什么通过反射调用RuntimeAssembly.GetExecutingAssembly会返回null?

先给大家还原一下问题场景:
根据.NET Framework的Assembly类源码,GetExecutingAssembly()内部是这么实现的:

public static Assembly GetExecutingAssembly() { 
    StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
    return RuntimeAssembly.GetExecutingAssembly(ref stackMark); 
}

当我们通过反射调用公开的Assembly.GetExecutingAssembly时,一切正常:

Type.GetType("System.Reflection.Assembly")
    .GetMethods(BindingFlags.Public | BindingFlags.Static)
    .Where(f => f.Name.Contains("GetCallingAssembly"))
    .First().Invoke(null, null)

但如果跳过公开方法,直接反射调用内部的RuntimeAssembly.GetExecutingAssembly,却始终返回null:

Type.GetType("System.Reflection.RuntimeAssembly")
    .GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
    .Where(f => f.Name.Contains("GetExecutingAssembly")).Skip(1) // 第二个重载接收一个参数
    .First().Invoke(null, new object[] { 
        Type.GetType("System.Threading.StackCrawlMark")
            .GetEnumValues().GetValue(1) // System.Threading.StackCrawlMark.LookForMyCaller
    })

问题的核心原因

这个坑的根源在于ref参数的传递方式错误,以及StackCrawlMark的工作机制:

  1. ref参数的反射调用要求
    你看,RuntimeAssembly.GetExecutingAssembly的方法签名是接收ref StackCrawlMark参数的,而不是普通值参数。在反射调用带ref/out修饰的方法时,你传递的不能只是一个枚举值的实例——你需要传递一个可被方法修改的引用变量。

你当前的代码只是把LookForMyCaller枚举值包装成对象数组传进去,但这是值传递,方法内部无法通过ref引用更新这个标记的状态,CLR也就没法正确追踪调用栈的上下文。

  1. StackCrawlMark的工作原理
    StackCrawlMark是CLR用来定位调用栈位置的标记。当你调用公开的Assembly.GetExecutingAssembly时,方法会先初始化一个StackCrawlMark变量,然后以ref的方式传给内部方法——这样CLR才能在方法内部修改这个标记,找到当前执行代码所在的程序集。

而你直接反射调用时,没有满足ref参数的传递要求,CLR无法完成栈追踪的过程,自然返回null。

  1. 额外提醒:内部类型的调用风险
    RuntimeAssembly是.NET Framework的内部类型,它的方法本来就不是设计给外部直接调用的,完全依赖CLR的内部调用约定。反射调用这类非公开内部方法本身就属于未被官方支持的场景,出现异常或者返回null都是意料之中的事。

内容的提问来源于stack exchange,提问作者SGKoishi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:27:52