1

増強したい

public static IObservable<TSource> Create<TSource>(
    Func<IObserver<TSource>, Action> subscribe)
{...}

F#で使用するため、関数またはアクションで呼び出すのではなく、標準のF#タイプを使用できますIObserver -> (unit -> unit)

どうすればこれを達成できますか?

編集:

完全な例を追加します。なぜ機能しないのかわからobsActionない。

open System
open System.Reactive
open System.Reactive.Disposables
open System.Reactive.Linq


type Observable with
  static member Create(subscribe) = 
    Observable.Create(fun observer -> Action(subscribe observer))

let obsDispose (observer:IObserver<_>) =
    let timer = new System.Timers.Timer()
    timer.Interval <- 1000.00
    let handlerTick = new Timers.ElapsedEventHandler(fun sender args ->     observer.OnNext("tick"))
    let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
    timer.Elapsed.AddHandler(handlerTick)
    timer.Elapsed.AddHandler(handlerElapse)
    timer.Start()
    Disposable.Empty

let obsAction (observer:IObserver<_>) =
    let timer = new System.Timers.Timer()
    timer.Interval <- 1000.00
    let handlerTick = new Timers.ElapsedEventHandler(fun sender args -> observer.OnNext("tick"))
    let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
    timer.Elapsed.AddHandler(handlerTick)
    timer.Elapsed.AddHandler(handlerElapse)
    timer.Start()
    let action() =
        timer.Elapsed.RemoveHandler(handlerTick)
        timer.Elapsed.RemoveHandler(handlerElapse)
        timer.Dispose()
    action

let obsOtherAction (observer:IObserver<_>) =
    let timer = new System.Timers.Timer()
    timer.Interval <- 1000.00
    let handlerTick = new Timers.ElapsedEventHandler(fun sender args -> observer.OnNext("tick"))
    let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
    timer.Elapsed.AddHandler(handlerTick)
    timer.Elapsed.AddHandler(handlerElapse)
    timer.Start()
    new System.Action( fun () ->
        timer.Elapsed.RemoveHandler(handlerTick)
        timer.Elapsed.RemoveHandler(handlerElapse)
        timer.Dispose())

let worksNeverStops = obsDispose |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
let actionWorks = obsOtherAction |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
let doesNotWork = obsAction |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
4

1 に答える 1

2

あなたが直面している問題はFPの落とし穴です。

の、

  static member Create(subscribe) = 
    Observable.Create(fun observer -> Action(subscribe observer))

のタイプはsubscribeですIObserver<_> -> unit -> unit

ここで、との間に微妙な違いがありIObserver<_> -> unit -> unit ます。違いは、前者はカレーで、後者はそうではないということです。IObserver<_> -> ActionAction : unit -> unit

オブザーバーがサブスクライブすると、getに適用できるsubscribe observerメソッドを返します。サブスクライブメソッドは、最後が適用されるまで実際に呼び出されることはありません。サブスクライブを解除するまでは呼び出されず、その時点で既にデタッチされます。()unit()

あなたはそれをカレーしないように強制することによってそれを乗り越えることができます:

let action() = ... | let action = (subscribe observer)
Action(action)

さらに遠く:

InvokeILをチェックすると、FastFunc生成されたのと同等のVB(関数参照はVBでより明確になります)バージョン

 static member Create(subscribe) = 
    Observable.Create(fun observer -> Action(subscribe observer))

は:

Friend Function Invoke(ByVal arg As IObserver(Of a)) As Action
    Return New Action(AddressOf New Observable-Create-Static@27-1(Of a)(Me.subscribe, arg).Invoke)
End Function

および:

  static member Create(subscribe) = 
    Observable.Create(fun observer ->
      let action = subscribe observer
      Action(action))

は:

Friend Function Invoke(ByVal arg As IObserver(Of a)) As Action
    Return New Action(AddressOf New Observable-Create-Static@28-1(Me.subscribe.Invoke(arg)).Invoke)
End Function
  1. AddressOf New Closure(Me.subscribe, arg).Invoke-> subscribe関数は、disposeアクションが呼び出されるまで呼び出されません。

  2. AddressOf New Closure(Me.subscribe.Invoke(arg)).Invoke->サブスクライブ関数が実際に呼び出され、結果のアクションが期待どおりに返されます。

最初のケースではなく、2番目のケースが機能する理由が明らかになったと思います。

于 2012-12-04T09:56:31.470 に答える