如何在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
相关产品推荐
相关产品推荐

