F# 的标准类型事件是什么?
What is a standard type event for F#?
我正在尝试从 F# 订阅/取消订阅 C# 制作的(在 RabbitMQ 客户端库中):
public event AsyncEventHandler<BasicDeliverEventArgs> Received;
public delegate Task AsyncEventHandler<in TEvent>(object sender, TEvent @event) where TEvent : EventArgs;
我成功订阅了活动:
let subscribeAsync (channel: IModel) exchange callback =
let consumer = AsyncEventingBasicConsumer(channel)
consumer.add_Received(AsyncEventHandler<BasicDeliverEventArgs>(fun sender args -> Task.CompletedTask))
// ...
话虽如此,我想知道为什么下面的代码无法编译:
let subscribeAsync (channel: IModel) exchange callback =
let consumer = AsyncEventingBasicConsumer(channel)
consumer.Received.AddHandler(AsyncEventHandler<BasicDeliverEventArgs>(fun sender args -> Task.CompletedTask))
// ...
因为我得到以下错误:
Program.fs(10, 14): [FS1091] The event 'Received' has a non-standard type. If this event is declared in another CLI language, you may need to access this event using the explicit add_Received and remove_Received methods for the event. If this event is declared in F#, make the type of the event an instantiation of either 'IDelegateEvent<_>' or 'IEvent<_,_>'.
我检查了 the official MS documentation 但我看不到任何关于 F# 标准事件类型的参考。
F# 会将 .NET 事件公开为 IEvent
或 IDelegateEvent
类型的值,具体取决于事件声明和委托类型。这只能用于具有一些基本公共结构的事件 - 当 F# 无法执行此操作时,它将公开事件的基础 add
和 remove
操作作为您可以直接调用的方法。
我不确定 "standard event type" 的规则是什么。但是,您可以从 the relevant bit of the F# compiler source code:
得到一些提示
let TryDestStandardDelegateType (infoReader: InfoReader) m ad delTy =
let g = infoReader.g
let (SigOfFunctionForDelegate(_, compiledViewOfDelArgTys, delRetTy, _)) =
GetSigOfFunctionForDelegate infoReader delTy m ad
match compiledViewOfDelArgTys with
| senderTy :: argTys when (isObjTy g senderTy) &&
not (List.exists (isByrefTy g) argTys) -> Some(mkRefTupledTy g argTys, delRetTy)
| _ -> None
所以,我的猜测是 "stadnard event type" 需要:
- 至少有一个参数
- 第一个参数的类型必须是
object
- 没有
byref
个参数
我正在尝试从 F# 订阅/取消订阅 C# 制作的(在 RabbitMQ 客户端库中):
public event AsyncEventHandler<BasicDeliverEventArgs> Received;
public delegate Task AsyncEventHandler<in TEvent>(object sender, TEvent @event) where TEvent : EventArgs;
我成功订阅了活动:
let subscribeAsync (channel: IModel) exchange callback =
let consumer = AsyncEventingBasicConsumer(channel)
consumer.add_Received(AsyncEventHandler<BasicDeliverEventArgs>(fun sender args -> Task.CompletedTask))
// ...
话虽如此,我想知道为什么下面的代码无法编译:
let subscribeAsync (channel: IModel) exchange callback =
let consumer = AsyncEventingBasicConsumer(channel)
consumer.Received.AddHandler(AsyncEventHandler<BasicDeliverEventArgs>(fun sender args -> Task.CompletedTask))
// ...
因为我得到以下错误:
Program.fs(10, 14): [FS1091] The event 'Received' has a non-standard type. If this event is declared in another CLI language, you may need to access this event using the explicit add_Received and remove_Received methods for the event. If this event is declared in F#, make the type of the event an instantiation of either 'IDelegateEvent<_>' or 'IEvent<_,_>'.
我检查了 the official MS documentation 但我看不到任何关于 F# 标准事件类型的参考。
F# 会将 .NET 事件公开为 IEvent
或 IDelegateEvent
类型的值,具体取决于事件声明和委托类型。这只能用于具有一些基本公共结构的事件 - 当 F# 无法执行此操作时,它将公开事件的基础 add
和 remove
操作作为您可以直接调用的方法。
我不确定 "standard event type" 的规则是什么。但是,您可以从 the relevant bit of the F# compiler source code:
得到一些提示let TryDestStandardDelegateType (infoReader: InfoReader) m ad delTy =
let g = infoReader.g
let (SigOfFunctionForDelegate(_, compiledViewOfDelArgTys, delRetTy, _)) =
GetSigOfFunctionForDelegate infoReader delTy m ad
match compiledViewOfDelArgTys with
| senderTy :: argTys when (isObjTy g senderTy) &&
not (List.exists (isByrefTy g) argTys) -> Some(mkRefTupledTy g argTys, delRetTy)
| _ -> None
所以,我的猜测是 "stadnard event type" 需要:
- 至少有一个参数
- 第一个参数的类型必须是
object
- 没有
byref
个参数