简体   繁体   中英

Is it possible to make a lazy event initializer in F#?

I have a server that pushes some data through a variety of RabbitMQ exchanges.

On the clients sides (there are multiple clients using different combination of data streams from the server), I have a common library that serves as an interface.

When that common library establishes contact with rabbit, it will create a listener queue for each exchange and expose events the client can subscribe to. So, in practice every client is listening to all the exchanges, even if they need just some of the data.

Part of the initialization code looks like that:

RabbitSubscriber(ExchangeChannel.ConsoleInfo.channelName exchange,   fun x -> JsonConvert.DeserializeObject<string>(x)               |> consoleInfoEvent.Trigger)   |> ignore
RabbitSubscriber(ExchangeChannel.ConsoleError.channelName exchange,  fun x -> JsonConvert.DeserializeObject<string>(x)               |> consoleErrorEvent.Trigger)  |> ignore
RabbitSubscriber(ExchangeChannel.Messages.channelName exchange,      fun x -> JsonConvert.DeserializeObject<string>(x)               |> messageEvent.Trigger)       |> ignore
...

and there are maybe 15 exchanges.

What I would like to figure out is if there is a way to detect when a client wants to subscribe to the event tied to a specific exchange (for example consoleInfoEvent in the first line) and initialize the queue ONLY if there is a subscription.

the events are exposed like this:

member this.OnConsoleInfoEvent    = consoleInfoEvent.Publish
member this.OnConsoleErrorEvent   = consoleErrorEvent.Publish
member this.OnConnectionEvent     = connectionEvent.Publish
...

in that case, I could reverse things where when a client is registering, (through.OnConsoleInfoEvent.Add...) I would initialize the client queue.

Is this possible to combine events and lazy? or is there a better mechanism?

When I try to make the publisher lazy, the code is executed right away:

let e = Event<string>()
let p = Lazy<IEvent<string>>(printfn "test"; e.Publish)

will print 'test', so there is something I didn't expect with Lazy as well.

Lazy constructor expects a lambda Lazy(fun () -> {exp}) alternatively you can use the lazy keyword lazy {exp} . Note that {} are just place holders, not computation expressions.

Example:

let p = Lazy<IEvent<string>>(fun () -> (printfn "test"; e.Publish))

or simply:

let p = lazy (printfn "test"; e.Publish)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM