Lecture thumbnail 0:00 / 0:00 So the mediator design pattern is a fairly common concern in development.
And as a result, many people have implemented their own libraries to support the mediator.
So we’re going to be talking about one of those libraries in this demo.
And the library I’ve chosen to talk about is called Mediator.
It’s spelled mediator with an R, So it’s somewhat different.
It’s missing a letter there.
And we’re going to take a look at how to use it.
So in this lesson, I’m just going to show you a basic demo of the library.
So in order to use the library, you of course have to get it from the NuGet package.
So let’s take a look at where that is located.
So if we just look at the NuGet packages, you’ll see that I’ve got two of them installed here.
So I’m using mediator.
So that’s the library which allows the mediator design pattern kind of wraps it.
And then I’m also using a dependency inversion framework called Autofac.
You can use a different dependency inversion framework.
It doesn’t really matter, but we’re going to be using those two to actually implement our mediator.
So how is this going to work?
Well, essentially the idea is just like in the previous discussions of the mediator, meaning that
you basically define your requests and you define the handlers for those requests, and then they all
go through some sort of central location.
But the way they go through a central location is somewhat invisible to you because it’s all configured
in the dependency inversion container.
So let’s suppose that we’re just going to simulate a very simple ping operation.
So what we’re going to be doing is we’re going to be taking a ping command and we’re going to be sending
that ping command, and then we’ll have handlers which receive the ping command and can do something
in response to that.
And we’re going to be doing all of this in the framework of mediator.
So first of all, let’s actually define the ping command.
So let’s just going to be a public class ping command and it’s going to implement an AI request interface.
So you can see this is a request that comes from mediator.
So we’re going to be implementing this.
And the generic type here is the response.
So when you send this command, what kind of response are you getting?
And the response we’re going to be expecting is going to be a pong response.
So Pong response is obviously going to have to be a type that we have to construct as well.
So we’ll make this type here.
And now in our command, you could typically specify the attributes, any kind of information you want
to put into a command.
But here I’m just going to leave this empty for the simplicity of the demo.
So here is Pong response.
This is where we want to actually basically handle the ping request somehow and maybe respond with something.
And this class doesn’t have to implement any interfaces because it’s the return value basically.
So here, for example, I can define that.
I want to return the timestamp when this request was actually received and when the response was generated.
So here I can do a public datetime timestamp like so and I can need to import system and I can for example,
initialize it in the constructor like so.
And that’s pretty much it.
That’s all that we want to do here.
Okay.
So we have a command that gets sent and we have a response, but where is the command processor who
actually processes the command?
Where is the handler?
So that’s the thing that we need to define next.
So we’re going to define a public class ping command handler, and this is also going to implement one
of those mediator or mediator rather, interfaces called a request handler.
So this is another interface that we get from mediator.
And here we have to specify two things in the argument.
So we have to specify the type of the request and the type of the response.
So the type of the request is ping command and the type of the response is pong response.
There we go.
Okay, so now we need to implement this interface, obviously.
So let’s do that.
I’ll just implement the missing members here.
So let’s wipe this out.
Now there’s one thing that’s missing here when you are returning a task, and that is the async keyword.
So what do we want to do?
Well, in this particular demo, since it’s a very simple demo, all we really want to do is we want
to return the response.
But of course, since we have to return a task of T, I’m going to await a task from result.
So in task from result, what we’re going to do is we’re going to construct the response.
So here I’ll say new Pong response with the current date time.
So maybe date time, UTC now something like that.
And then just to avoid any kind of potential deadlocks, if you’re going to be calling this synchronously
from UI, for example, I’m going to configure a wait false.
Okay, So that’s.
That’s pretty much it.
That’s our command handler.
Now, you’ll notice that the command handler is is not instantiated anywhere.
And in actual fact, it’s never going to be instantiated directly because it’s going to be configured
inside the dependency injection framework.
So what you might want to do is you might want to annotate it with the used implicitly attribute, used
implicitly.
Of course, this is part of the jetbrains annotation.
So if you go onto NuGet once again and you know, there is a there is a context section here to just
search for this type, you’ll see that Jetbrains dot Annotations is here.
So let’s just quickly add this to the project because then what’s going to happen is the static analysis
tools will no longer complain that we are we’re not instantiating this class.
So coming down here, I can alt enter and I can just, just have that jetbrains dot annotations up above.
And so now you’ll notice there is no highlighting saying this class is not used.
That’s just a little thing.
Okay, so now here is the fun part where we configure the container.
So this obviously depends on the dependency injection framework that you use.
I prefer Autofac and I have a course on dependency injection with Autofac that you might want to check
out.
So let’s start by making the container builder so new container builder like so.
And that is coming from Autofac.
So I need to, I need to import all the right things here.
Okay.
So now that we have that, we have to register two things.
We have to register the mediator and also the service factory, which is another component from mediator.
So first of all, build a dot register type.
So we’re registering mediator.
As an AI mediator.
As an AI mediator.
Like this.
And we’re making it effectively a singleton.
We’re saying instance per lifetime scope, which means that there’s going to be just one instance of
it anywhere.
So that’s a kind of kosher way of making a singleton.
So the second thing you need to do is you need to register a service factory and that is another mediator
thingy.
And that service factory is basically going to well, you’ll see how it works in a moment.
So builder dot register.
So we register with a generic argument here.
Service factory.
Okay.
So did I misspell this somehow?
Builder builder.
That’s.
That’s just being weird.
What’s going on here?
Hold on.
Builder dot register.
Now, register is definitely here.
Yes, there is a generic register which takes a service factory.
I don’t know why this thing doesn’t see it.
And then you take the context set and you use it inside a function.
Okay, so what we want to do with the context and the formatter is being crazy here.
I want to go into a new line so you resolve the I component context.
So you say var C equals context dot result C dot resolve I components context I component context is
a, an autofac thingy.
And then once you resolve that, you use the I component context to actually resolve a particular type
and you return that.
So you return a lambda which takes a given type and then uses the component context to resolve that
type.
That’s pretty much it.
So this is just some necessary plumbing that you have to do.
It’s a once we are done with it, we can sort of start using everything.
But of course we also have to register all the the request responses, all the rest of it inside the
container as well, because what we’re going to be doing is we’re going to be resolving the mediator
and then sending some sort of command through the mediator.
So the way it works is, well, you can just go ahead and register everything inside the current assembly.
So that’s what I’m going to do.
You can register things individually, but it’s easier to just go register assembly types and then grab
the current assembly.
So let’s grab the current assembly, which is type of program, dot assembly.
So we grab the current assembly and that’s, that’s it.
We register it as implemented interfaces.
So basically if a type implements some it, you’re going to register that request for it, return that
it for every single assembly or every single type inside the current assembly basically.
So now that we’re done, now that we’ve registered everything in the container builder, we can actually
build the container itself.
So var container equals builder dot build.
So we’ve built the thing and then we can use the container to resolve the mediator.
So I can say var mediator equals container dot resolve I mediator.
So a mediator is the mediator interface type from the mediator library.
And then what I can do is I can send a ping command and actually get a response.
So I can say var response equals await mediator, dot send.
You’ll notice it’s kind of using async await mechanisms everywhere.
And I send a new ping command.
So you’ll notice there’s also a cancellation token here and other useful stuff.
So we’re sending the ping command.
And now what we want to do is maybe we want to print a response.
So.
CW So I just want to say that, uh, we got a response at and then specify the actual time, which is
response dot timestamp.
There we go.
So it’s everything is almost correct, except that you now have to modify your public static void main
to incorporate the async keyword async like so.
And that’s pretty much it.
So that’s our Oh wait, no, that’s not it.
You have to have a task as opposed to just a void.
Async void is not legal.
Okay.
So let’s take a look at what’s going on here.
Apparently, we have to adjust the language version.
So let’s go into the project settings.
This is one of those really, really annoying things.
So now now we’re finally done.
We can actually run this demo and see what we get here.
So let’s make a configuration.
Just just run the whole thing and hopefully we get our result.
Okay, so compiling and here is the output.
So the takeaway from this small demo is that there is a library, at least one library that might be
more libraries, but the mediator library is kind of well known.
So this library allows you to set up a mediator and then plug it into a dependency injection framework
and get the components communicating with one another without really having to do anything.
So you’ll notice that we automatically registered everything down here.
But when it came to actually handling the ping command, we didn’t do it explicitly.
So what happened is every single type, which was specified as a handler for the ping command, actually
got to process the message and do something with it.
Notice also the cancellation token.
So basically one of those commands can both process the message and then say that the further subsequent
processing isn’t really required.
So it can use the cancellation token to actually cancel the whole thing.
So that’s very useful.
That’s just being an overview of mediator.
I hope you like it.
It’s a useful library.
It’s very minimal and it works with any dependency injection framework.
It works with ASP net if you’re into that sort of thing.
So it’s very versatile and I recommend that you use it if you can.
Play Play Play Stop Start Play information alert