开发者

Referencing Asynchronous F# datatype from C#

开发者 https://www.devze.com 2023-03-23 02:34 出处:网络
I created a F# library that returns this datatype FSharpAsync<IEnumerable<Tupel<DateTime,string>>>

I created a F# library that returns this datatype

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

How do I access the FSharpAsync type so I can enumerate through the tuple from C# and print out the conte开发者_C百科nt?


It is generally not recommended to expose F# types such as FSharpAsync in a public interface that will be used by C# clients (see F# component design guidelines). You can use Async.StartAsTask (on the F# side) to expose the operation as a Task<T> that is easy to use from C#.

In fact, I would also replace the tuple with a named type (that captures the meaning of the data structure). Tuples can be used in C#, but they are not idiomatic in 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) } }

Now, to expose the operation to C#, the best practice is to use a type with an overloaded static method. The method starts the operation as a task and one overload specifies cancellation token. The C# naming convention for these is to add Async to the end of the name (which doesn't overlap with F# which adds Async to the front):

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

Your C# code can then use Work.DoWorkAsync() and work with the task in the usual C# style. It will even work with the await keyword that will be (probably) added to C# 5.


Reference FSharp.Core.dll, then:

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

FSharpAsync is in the Microsoft.FSharp.Control namespace.

FSharpOption is in the Microsoft.FSharp.Core namespace.


You can manipulate it via the static methods of FSharpAsync. The async you're getting is likely of type Async<'T>, which has no instance methods.


If you look at the return type FSharpAsync<IEnumerable<Tupel<DateTime,string>>> this tell us that it is a async operation that when gets executed by the static methods in FSharpAsync will return a IEnumerable<Tupel<DateTime,string>>, so this becomes a case where the F# library create a operation (the async operation) that your C# code can execute, so it act as lazy operation that you can execute later after getting it from F# library and when you execute this lazy operation it returns you a IEnumerable which it self is sort of lazy in the sense that you pull values from it and at the same times the values are generated.

I think you can just return then IEnumerable<Tupel<DateTime,string>> from your F# library and doesn't need to return Async operation at all. But again this depends on what your F# library does and how it is supposed to generate this IEnumerable

0

精彩评论

暂无评论...
验证码 换一张
取 消