转换Lambda表达式触发CS1660错误?PowerShell扩展Websocket.Client遇阻
问题场景
需要优化PowerShell脚本实现多源信息收集的事件驱动处理,其中WebSocket数据源选用Websocket.Client模块,该模块原生不支持触发.NET事件,因此尝试继承WebsocketClient类扩展自定义事件,但编译时出现CS1660错误。
自定义扩展类代码
if (-not ("WebsocketClientExt" -as [type])) { $cp = @" using System; using System.Net; using System.Net.WebSockets; using Websocket.Client; using Websocket.Client.Models; public class WebsocketClientExt : WebsocketClient { public event EventHandler<DisconnectionInfo> Disconnection; public WebsocketClientExt( Uri url ): base(url) { } public void SubscribeEvents () { DisconnectionHappened.Subscribe(info => Disconnection?.Invoke(this, info)); } } "@ Add-Type -TypeDefinition $cp -ReferencedAssemblies @( 'Websocket.Client', 'System.Net.WebSockets', 'System.Net.WebSockets.Client' ) }
编译错误信息
Add-Type: Line | 22 | Add-Type -TypeDefinition $cp -ReferencedAssemblies @( 'Websocket. … | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | (15,41): error CS1660: Impossible de convertir expression lambda en type 'IObserver<DisconnectionInfo>', car il ne s'agit pas d'un type délégué DisconnectionHappened.Subscribe(info => Disconnection?.Invoke(this, info));
英文释义:无法将Lambda表达式转换为“IObserver
”类型,因为它不是委托类型。
错误原因
DisconnectionHappened是IObservable<DisconnectionInfo>类型,其原生Subscribe方法要求传入实现IObserver<DisconnectionInfo>接口的对象,而非直接传入Lambda表达式。你提到的EventHandler是委托类型,但这里的问题在于IObservable的订阅机制依赖Reactive Extensions(Rx)的扩展方法才能支持Lambda参数,当前代码未引用对应的Rx程序集。
解决方案
方案1:添加Rx程序集引用并使用扩展方法
修改Add-Type的引用列表,加入System.Reactive.Linq,即可使用支持Lambda的Subscribe扩展方法:
if (-not ("WebsocketClientExt" -as [type])) { $cp = @" using System; using System.Net; using System.Net.WebSockets; using Websocket.Client; using Websocket.Client.Models; public class WebsocketClientExt : WebsocketClient { public event EventHandler<DisconnectionInfo> Disconnection; public WebsocketClientExt( Uri url ): base(url) { } public void SubscribeEvents () { DisconnectionHappened.Subscribe(info => Disconnection?.Invoke(this, info)); } } "@ # 添加System.Reactive.Linq引用 Add-Type -TypeDefinition $cp -ReferencedAssemblies @( 'Websocket.Client', 'System.Net.WebSockets', 'System.Net.WebSockets.Client', 'System.Reactive.Linq' ) }
方案2:手动实现IObserver接口
如果不想依赖Rx扩展,可以自定义实现IObserver<DisconnectionInfo>来处理断开事件:
if (-not ("WebsocketClientExt" -as [type])) { $cp = @" using System; using System.Net; using System.Net.WebSockets; using Websocket.Client; using Websocket.Client.Models; public class WebsocketClientExt : WebsocketClient { public event EventHandler<DisconnectionInfo> Disconnection; private DisconnectionObserver _disconnectionObserver; public WebsocketClientExt( Uri url ): base(url) { _disconnectionObserver = new DisconnectionObserver(this); } public void SubscribeEvents () { DisconnectionHappened.Subscribe(_disconnectionObserver); } private class DisconnectionObserver : IObserver<DisconnectionInfo> { private readonly WebsocketClientExt _parent; public DisconnectionObserver(WebsocketClientExt parent) { _parent = parent; } public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(DisconnectionInfo value) { _parent.Disconnection?.Invoke(_parent, value); } } } "@ Add-Type -TypeDefinition $cp -ReferencedAssemblies @( 'Websocket.Client', 'System.Net.WebSockets', 'System.Net.WebSockets.Client' ) }
补充说明
两种方案中,方案1更简洁——Websocket.Client本身依赖Reactive Extensions,添加引用不会引入额外依赖;方案2则完全不依赖Rx扩展方法,适合需要最小化依赖的场景。
内容的提问来源于stack exchange,提问作者Alain
相关产品推荐
相关产品推荐

