Only a little over 3 months, I released v1.0 of Mediator. Since then, I’ve been adding features as fast as they come to mind. The focus on making the Mediator
pattern upfront for apps (in my opinion) has been a huge success. I’ve been using it in my MAUI apps for offline, caching, & resiliency middleware. The amount of time
it saves me is pretty crazy.
Since version the v1 release, I’ve been adding a ton of features including an ASP.NET extension for HTTP endpoints straight to Mediator request handlers. Quite recently - I found a lot of mediated calls would end up just wrapping HTTP calls done with Refit or Kiota. I decided to add my
own source generator to deal with this. Check out the HTTP Extension for more on this.
What’s New in 2.0
So what does 2.0 bring that requires a major version bump? The first major feature is that I’ve brought the offline, stream replay, and user error notification middleware to Blazor webassembly. This middleware was already
present in MAUI, but Blazor needed a “connectivity” & “storage” service to match MAUI.
The second major feature is that I’ve been moving a lot of the middleware to be configured via Microsoft.Extensions.Configuration. This allows you to configure
middleware and handlers in a global way and without polluting your code with attributes everywhere. Below is an example of all configuration we offer now:
So let’s unpack this. The first thing to notice is that we have ”*” to “glob” a namespace or ALL calls. If you want to attack a specific contract, just fully label it.
We will find the nearest namespace to your contract before giving up as “not enabled” for a feature to be disabled on a contract.
What’s Next
I’m pretty happy with this release, but I still have a ton of ideas. All the stuff you can do around the handlers with middleware is really exciting. Have an idea for the mediator,
head on over to GitHub and add a feature request. I’m always looking for new ideas.
Shiny Mediator is something new I’ve been working on. I love Jimmy Bogard’s MediatR library on the server, but I just couldn’t
get it to fit the way I wanted for Apps… especially Blazor & .NET MAUI apps.
What is a mediator? It’s a small in-process version of a message bus. MAUI has MessagingCenter, the Community toolkit has the weak message center, and Prism
offers an event aggregator. They’re all great, but they lack in areas that I want “more”.
If an event errors, the whole chain dies in the publish
Events are fired in a foreach (mostly)
You have to tie into them and unsubscribe from them or you can leak memory
They don’t provide the concept of command or request/response models (a command can only be responded to by a single handler)
They don’t provide any sort of middleware (pre & post handling)
Sure - they aren’t geared for these things, but the question is “what is”?
Some might say “this is overengineering” or “too complex”. I would counter that comment by saying that this can actually simplify your architecture
overall by removing a lot of complex plumbing around services, references, and navigation.
Let’s go over some of the problems that we use mediator to solve within our apps
What Does It Solve
We believe that Shiny Mediator is the answer to these problems. It’s a simple, yet powerful library that allows you to create a mediator in your app
Problem #1 - Service & Reference Hell
Does this look familiar to you?
With a bit of our middleware and some events, you can get here:
Problem #2 - Messages EVERYWHERE (+ Leaks)
Do you use the MessagingCenter in Xamarin.Forms? It’s a great tool, but it can lead to some memory leaks if you’re not careful. It also doesn’t have
a pipeline, so any errors in any of the responders will crash the entire chain. It doesn’t have a request/response style setup (not that it was meant for it), but
this means you still require other services.
Let’s take a look at our mediator in action for this scenarios
Problem #3 - Strongly Typed Navigation with Strongly Typed Arguments
Our amazing friends over in Prism offer the “best in class” MVVM framework. We’ll them upsell you beyond that, but one
of their amazing features is ‘Modules’. Modules help break up your navigation registration, services, etc.
What they don’t solve is providing a strongly typed nature for this stuff (not their job though). We think we can help
addon to their beautiful solution.
A normal call to a navigation service might look like this:
This is great. It works, but I don’t know the type OR argument requirements of “MyPage” without going to look it up. In a small project
with a small dev team, this is fine. In a large project with a large dev team, this can be difficult.
Through our Shiny.Framework library we offer a GlobalNavigationService that can be used to navigate to any page in your app from anywhere, however,
for the nature of this example, we’ll pass our navigation service FROM our viewmodel through the mediator request to ensure proper scope.
Now, in your viewmodel, you can do this:
Strongly typed. No page required page knowledge from the module upfront. The other dev team of the module can define HOW things work.
Closing
Lastly, we offer some absolutely epic middleware that you can use to do things like logging, caching, error handling, etc.
Check out our middleware documentation for more information.
Check out our overall documentation for more information on how to use the mediator in your app. We think you’ll love it!