Ссылка на асинхронный тип данных F # из С#

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

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

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

Ответ 1

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

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

// 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) } }

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

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

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

Ответ 2

Ссылка 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.

Ответ 3

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

Ответ 4

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

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