Ссылка на асинхронный тип данных F # из C # - PullRequest
11 голосов
/ 25 июля 2011

Я создал библиотеку F #, которая возвращает этот тип данных

FSharpAsync<IEnumerable<Tupel<DateTime,string>>>

Как мне получить доступ к типу FSharpAsync, чтобы я мог перечислять через кортеж из C # и распечатывать содержимое?

Ответы [ 4 ]

14 голосов
/ 25 июля 2011

Обычно не рекомендуется выставлять типы F #, такие как FSharpAsync, в общедоступном интерфейсе, который будет использоваться клиентами C # (см. Рекомендации по проектированию компонентов F # ). Вы можете использовать Async.StartAsTask (на стороне F #), чтобы представить операцию как Task<T>, которую легко использовать из C #.

Фактически, я бы также заменил кортеж на именованный тип (который отражает значение структуры данных). Кортежи могут использоваться в C #, но они не являются идиоматическими в C #:

// Assuming you have an operation like this 
let asyncDoWork () : Async<seq<DateTime * string>> = (...)

// Define a named type that explains what the date-string pair means
type Item(created:DateTime, name:string) =
  member x.Created = created
  member x.Name = name

// Create a simple wrapper that wraps values into 'Item' type
let asyncDoWorkItems () = 
  async { let! res = asyncDoWork()
          return seq { for (d, n) in res -> Item(d, n) } }

Теперь, чтобы представить операцию на C #, лучше всего использовать тип с перегруженным статическим методом. Метод запускает операцию как задачу, и одна перегрузка указывает токен отмены. Соглашение об именах C # для них заключается в добавлении Async к end имени (которое не совпадает с F #, которое добавляет Async впереди):

type Work = 
  static member DoWorkAsync() =
    Async.StartAsTask(asyncDoWorkItems())
  static member DoWorkAsync(cancellationToken) =
    Async.StartAsTask(asyncDoWorkItems(), cancellationToken = cancellationToken)

Ваш код C # может затем использовать Work.DoWorkAsync() и работать с задачей в обычном стиле C #. Он даже будет работать с ключевым словом await, которое (вероятно) будет добавлено в C # 5.

4 голосов
/ 16 марта 2012

Ссылка на FSharp.Core.dll, затем:

FSharpAsync<IEnumerable<Tupel<DateTime,string>>> async = ...
IEnumerable<Tuple<DateTime, string>> result = FSharpAsync.RunSynchronously(async, timeout: FSharpOption<int>.None, cancellationToken: FSharpOption<CancellationToken>.None);

FSharpAsync находится в пространстве имен Microsoft.FSharp.Control.

FSharpOption находится в пространстве имен Microsoft.FSharp.Core.

0 голосов
/ 25 июля 2011

Если вы посмотрите на тип возвращаемого значения FSharpAsync<IEnumerable<Tupel<DateTime,string>>>, это говорит нам о том, что это асинхронная операция, которая при выполнении статическими методами в FSharpAsync возвращает IEnumerable<Tupel<DateTime,string>>, так что это становится случаем, когда библиотека F # создаетоперация (асинхронная операция), которую может выполнить ваш код C #, поэтому он действует как ленивая операция, которую вы можете выполнить позже после получения ее из библиотеки F #, и когда вы выполняете эту ленивую операцию, она возвращает вам IEnumerable, который сам по себе ленивощущение, что вы извлекаете из него значения, и в то же время они генерируются.

Я думаю, что вы можете просто вернуть IEnumerable<Tupel<DateTime,string>> из вашей библиотеки F # и вообще не нужно возвращать асинхронную операцию.Но опять же, это зависит от того, что делает ваша библиотека F # и как она должна генерировать этот IEnumerable

0 голосов
/ 25 июля 2011

Вы можете управлять им с помощью статических методов FSharpAsync .async, который вы получаете, скорее всего, типа Async<'T>, у которого нет методов экземпляра.

...