Что такое стандартное событие типа для F #? - PullRequest
2 голосов
/ 03 марта 2020

Я пытаюсь подписаться / отписаться на C# -рабочий (в клиентской библиотеке RabbitMQ) от F #:

AsyncEventingBasicConsumer.cs

public event AsyncEventHandler<BasicDeliverEventArgs> Received;

AsyncEventHandler.cs

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<_,_>'.

Я проверил официальную документацию MS но я не вижу ссылки на тип стандартного события для F #.

1 Ответ

2 голосов
/ 03 марта 2020

F # будет представлять. NET события как значения типа IEvent или IDelegateEvent, в зависимости от того, как выглядят объявление события и тип делегата. Это может быть сделано только для событий, которые имеют некоторую базовую c общую структуру - когда F # не может сделать это, он будет представлять основные операции add и remove события как методы, которые вы можете вызывать напрямую.

Я не совсем уверен, каковы правила для того, что считается "стандартным типом события". Тем не менее, вы можете получить некоторую подсказку от соответствующего бита исходного кода компилятора F # :

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» должен:

  • Имеет хотя бы один параметр
  • Первый параметр должен иметь тип object
  • Нет byref параметров
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...