, , , , , , Code Review SE. Samuel Jack .NET, , 4 CodeProject #.
module Observable =
open System
// ('a -> 'b -> unit) -> 'a -> IObservable<'b>
let subscribeWeakly callback target source =
let mutable sub:IDisposable = null
let mutable disposed = false
let wr = new WeakReference<_>(target)
let dispose() =
lock (sub) (fun () ->
if not disposed then sub.Dispose(); disposed <- true)
let callback' x =
let isAlive, target = wr.TryGetTarget()
if isAlive then callback target x else dispose()
sub <- Observable.subscribe callback' source
sub
. WeakSubscriber.
!
me. this , , . ( ?), "" , let. ( private.)
:
type Publisher() =
let myEvent = new Event<_>()
[<CLIEvent>] member this.MyEvent = myEvent.Publish
member this.Trigger(x) = myEvent.Trigger(x)
type StrongSubscriber() =
member this.MyMethod x =
printfn "Strong: method received %A" x
member this.Subscribe(publisher:Publisher) =
publisher.MyEvent |> Observable.subscribe this.MyMethod
publisher.MyEvent |> Observable.subscribe
(fun x -> printfn "Strong: lambda received %A" x)
type WeakSubscriber() =
member this.MyMethod x =
printfn "Weak: method received %A" x
member this.Subscribe(publisher:Publisher) =
publisher.MyEvent |> Observable.subscribeWeakly
(fun (me:WeakSubscriber) x -> me.MyMethod x) this
publisher.MyEvent |> Observable.subscribeWeakly
(fun _ x -> printfn "Weak: lambda received %A" x) this
:
[<EntryPoint>]
let main argv =
let pub = Publisher()
let doGc() =
System.GC.Collect()
System.GC.WaitForPendingFinalizers()
System.GC.Collect()
printfn "\nGC completed\n"
let someScope() =
let strong = StrongSubscriber()
let weak = WeakSubscriber()
strong.Subscribe(pub)
weak.Subscribe(pub)
doGc()
printfn "All subscribers should still be triggered:"
pub.Trigger(1)
someScope()
doGc()
printfn "Weak subscribers should not be triggered:"
pub.Trigger(2)
System.Console.ReadKey() |> ignore
0
:
GC completed
All subscribers should still be triggered:
Strong: method received 1
Strong: lambda received 1
Weak: method received 1
Weak: lambda received 1
GC completed
Weak subscribers should not be triggered:
Strong: method received 2
Strong: lambda received 2