在F#中使用EasyNetQ订阅RabbitMQ主题时遭遇编译错误
这个编译错误的核心原因是你传递给Subscribe方法的configure参数类型不匹配,我来帮你拆解问题并给出解决方案:
错误根源分析
从报错信息可以看到,EasyNetQ的Subscribe方法期望的configure参数是C#的Action<ISubscriptionConfiguration>类型,对应F#里的ISubscriptionConfiguration -> unit(即接收配置对象、执行操作但不返回任何值的函数)。
但你写的fun (x:ISubscriptionConfiguration) -> x.WithTopic("app.queue")返回的是修改后的ISubscriptionConfiguration对象,函数类型是ISubscriptionConfiguration -> ISubscriptionConfiguration,这和方法要求的类型完全不兼容,所以编译器抛出了FS0041错误。
解决方案
只需要修改configure函数,让它执行WithTopic操作后忽略返回值,把函数类型适配成unit返回即可,具体有两种简洁写法:
写法1:用|> ignore忽略返回值
直接在WithTopic调用后加上|> ignore,让函数返回unit:
let subscribeToAppQueueWithTopic (callback : Subscription<AppEnvelope>) = bus.PubSub.Subscribe<AppEnvelope>( String.Empty, callback.OnMessageReceived, (fun (x:ISubscriptionConfiguration) -> x.WithTopic("app.queue") |> ignore), cts.Token )
写法2:显式包装成Action
如果更习惯C#风格的写法,也可以显式创建Action<ISubscriptionConfiguration>对象,F#会自动忽略WithTopic的返回值以适配Action的void要求:
let subscribeToAppQueueWithTopic (callback : Subscription<AppEnvelope>) = bus.PubSub.Subscribe<AppEnvelope>( String.Empty, callback.OnMessageReceived, Action<ISubscriptionConfiguration>(fun x -> x.WithTopic("app.queue")), cts.Token )
额外提示:修复SubscribeAsync版本
你注释掉的subscribeAsyncToAppQueueWithTopic函数也可以用同样的方法修复,只需要调整configure参数:
let subscribeAsyncToAppQueueWithTopic (callback : Subscription<AppEnvelope>) = async { do! bus.PubSub.SubscribeAsync<AppEnvelope>( String.Empty, callback.OnMessageReceived, fun (x: ISubscriptionConfiguration) -> x.WithTopic("scanservice.queue") |> ignore, cts.Token ) |> Async.AwaitTask } |> Async.Start
这样修改后,你的F#代码就能正常编译,并且正确订阅指定主题的RabbitMQ消息了。
内容的提问来源于stack exchange,提问作者Canacourse

