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

如何在NSubstitute 3.1中使用ref参数触发委托事件?

在NSubstitute 3.1中触发带ref参数的委托事件的解决方案

嗨Oliver,我之前维护老项目时也碰到过一模一样的问题——NSubstitute 3.x的Raise.Event工具类确实对ref/out参数支持有缺陷,编译器报错完全在意料之中。不过不用急,咱们可以绕开这个限制,手动触发事件,亲测在3.1版本下完美可行!

核心思路:直接调用事件的委托调用列表

NSubstitute的Raise.Event在3.x版本没法处理ref参数,但我们可以跳过它,直接获取事件注册的所有委托,手动调用Invoke方法,这样就能正常传递ref参数了。

代码示例(事件为public的情况)

如果你的OnGetData事件是public的,直接这么写就行:

var theKey = "test";
byte[] theData = null;

// 获取事件上注册的所有委托
var registeredHandlers = _theObject.OnGetData?.GetInvocationList();
if (registeredHandlers != null)
{
    foreach (GetDataHandler handler in registeredHandlers)
    {
        // 直接调用委托,ref参数可以正常传递
        handler.Invoke(theKey, ref theData);
    }
}

代码示例(事件为非public的情况)

如果OnGetData是private或者internal的,那就需要用反射来获取委托列表:

var theKey = "test";
byte[] theData = null;

// 通过反射获取事件对应的字段(NSubstitute代理对象中事件会对应一个字段)
var eventType = _theObject.GetType();
var eventInfo = eventType.GetEvent("OnGetData");
var eventField = eventType.GetField(
    eventInfo.Name, 
    BindingFlags.Instance | BindingFlags.NonPublic
);

var registeredHandlers = eventField.GetValue(_theObject) as Delegate[];
if (registeredHandlers != null)
{
    foreach (GetDataHandler handler in registeredHandlers)
    {
        handler.Invoke(theKey, ref theData);
    }
}

为什么这个方法有效?

NSubstitute生成的代理对象会正常维护事件的委托注册列表,GetInvocationList()(或通过反射拿到的字段值)能准确获取到你在单元测试中注册的所有事件处理方法。直接调用委托的Invoke方法,完全遵循C#对ref参数的语法规则,不会触发编译器报错。

这个方案不需要升级NSubstitute版本,完全适配3.1,我在几个老项目里都用过,没出过问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:02:42