Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Rocky LIU Yan
Rocky LIU Yan

Posted on

Request -> Handler -> SubPub Pattern with MediatR or Raw F# code

We will try:

  • MediatR
  • Mailbox
  • Event
  • Rx
  • Agent

MediatR

Example:

openMediatR// Define the request type inheriting from `IRequest`. Here it's `MyRequest`.typeMyRequest()=inheritIRequest// Define the handler that takes the request as a parameter.lethandler(req:MyRequest)=printfn"Handling request"// Get the singleton instance of `Mediator`.letmediator=Mediator.Instance// Create the request.letreq=MyRequest()// Use `mediator.Send` to send the request and pipe the return value to the `handler`.mediator.Send(req)|>handler`
Enter fullscreen modeExit fullscreen mode

Main steps:

  • Define a request type inheriting from IRequest. Here it's MyRequest.
  • Define a handler function handler that takes a request as a parameter.
  • Obtain a singleton instance of Mediator.
  • Create a request req.
  • Use mediator.Send to send the request and pass the return value through the handler.
  • This allows you to use MediatR's pipeline to send commands or requests and handle them. You can continue to expand by adding more request types, handlers, etc.

Next, design a subscription:

openMediatR// Define the event type inheriting from `INotification`. Here it's `MyEvent`.typeMyEvent()=inheritINotification// Define the event handler function.lethandler(evt:MyEvent)=printfn"Handling event"letmediator=Mediator.Instance// Subscribe to the event.mediator.Subscribe(typeof<MyEvent>,handler)// Publish the event.mediator.Publish(MyEvent())
Enter fullscreen modeExit fullscreen mode

Main steps:

  • Define an event type inheriting from INotification. Here it's MyEvent.
  • Define an event handler function handler that takes an event as a parameter.
  • Get the singleton instance of Mediator.
  • Use mediator.Subscribe to subscribe to the event, specifying the event type and handler.
  • Use mediator.Publish to publish the event.

This allows you to implement a publish-subscribe pattern. You can continue to expand by adding more event types, handlers, etc.

Combining them: Using F# functional programming style, combine the request handler and event subscription into a MediatR example:

openMediatR// Define the request.typeSayHelloRequest(name:string)=inheritRequestmemberthis.Name=name// Define the handler.letsayHelloHandler(request:SayHelloRequest)=printfn"Hello %s"request.Name// Define the event.typeUserGreetedEvent(name:string)=inheritNotificationmemberthis.Name=name// Define the event handler.letuserGreetedHandler(evt:UserGreetedEvent)=printfn"User %s was greeted"evt.Name// Request handling process.letsendHellonamemediator=letrequest=SayHelloRequest(name)mediator.Send(request)|>sayHelloHandler// Event subscription.letsubscribemediator=mediator.Subscribe(typeof<UserGreetedEvent>,userGreetedHandler)// Orchestrator function combining calls.letorchestratormediatorname=subscribemediatorsendHellonamemediatormediator.Publish(UserGreetedEvent(name))// Get the Mediator and run.letmediator=Mediator.Instanceorchestratormediator"John"
Enter fullscreen modeExit fullscreen mode

Running result:

Hello John  User John was greeted
Enter fullscreen modeExit fullscreen mode

By calling MediatR's Send method to send a request, Subscribe method to subscribe to an event, and Publish method to publish an event, you can implement both request-response and publish-subscribe patterns.

F# raw code

Can F# bare code implement the request and subscription pattern?

Certainly. You can use MailboxProcessor, but the encapsulation and ease of use are not as good as MediatR.

Here's an example of implementing subscriptions with MailboxProcessor without using MediatR, just using F# language features:

// Define the request type.typeSayHelloRequest={Name:string}// Define the event type.typeUserGreetedEvent={Name:string}// Request handling function.letsayHelloHandler(request:SayHelloRequest)=printfn"Hello %s"request.Name// Event handling function.letuserGreetedHandler(event:UserGreetedEvent)=printfn"User %s was greeted"event.Name// Use a pipeline to send a request.letsendRequestname={Name=name}|>sayHelloHandler// Use event subscription with `MailboxProcessor`.letpublisher=MailboxProcessor.Start(funinbox->letrecloop()=async{let!event=inbox.Receive()userGreetedHandlereventreturn!loop()}loop())// Publish an event.letpublishname=publisher.Post({Name=name})// Orchestrator.letorchestratorname=sendRequestnamepublishnameorchestrator"John"
Enter fullscreen modeExit fullscreen mode

Listing other methods:

For example, you can use:

  1. The Event type:
typeEvent<'T>=delegateofsender:obj*evt:'T->unit
Enter fullscreen modeExit fullscreen mode

Then define the event handling function as a delegate of this type:

lethandler(s,e)=printfn"Handling event: %A"e
Enter fullscreen modeExit fullscreen mode

Subscribe to the event:

letevent=Event<UserGreetedEvent>()event.Publish(handler)
Enter fullscreen modeExit fullscreen mode

Publish the event:

event.Trigger(this,{Name="John"})
Enter fullscreen modeExit fullscreen mode
  1. Rx (Reactive Extensions) can use Rx's Subject to replace events:
letsubject=newSubject<'T>()subject.OnNext(event)|>ignoresubject.Subscribe(handler)
Enter fullscreen modeExit fullscreen mode
  1. Agent can use Agent's Post and Receive for message passing:
letagent=Agent.Start(funinbox->letrecloop()=async{let!msg=inbox.Receive()handlermsgreturn!loop()}loop())agent.Post(event)
Enter fullscreen modeExit fullscreen mode

End of the article, discussion is welcome.

The code is for reference only. Please modify it yourself if you want to run it.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Joined

More fromRocky LIU Yan

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp