Quick Start
MAUI
-
First, let’s create our request & event handlers
using Shiny.Mediator;public record TestCommand(string AnyArgs, int YouWant) : ICommand;public record TestEvent(MyObject AnyArgs) : IEvent;// and for request/response requests - we'll come back to thispublic record TestResponseRequest : IRequest<TestResponse> {}public record TestResponse {} -
Next - let’s wire up our handlers. You can have ONLY 1 request handler per request type. This is where you would do the main business logic or data requests.
Let’s create our Request & Command Handlers
using Shiny.Mediator;// NOTE: Request handlers are registered as singletonspublic class TestCommandHandler : ICommandHandler<TestCommand>{// you can do all dependency injection herepublic async Task Handle(TestCommand command, CommandContext<TestCommand> context, CancellationToken ct){// do something async here}}public class TestResponseRequestHandler : IRequestHandler<TestResponseRequest, TestResponse>{public async Task<TestResponse> Handle(TestResponseRequest request, RequestContext<TestResponseRequest> context, CancellationToken ct){var response = await GetResponseThing(ct);return response;}}public class TestEventHandler : IEventHandler<TestEvent>{// Dependency injection works herepublic async Task Handle(TestEvent @event, CancellationToken ct){// Do something async here}} -
Now, let’s register all of our stuff with our .NET MAUI MauiProgram.cs
public static class MauiProgram{public static MauiApp CreateMauiApp(){var builder = MauiApp.CreateBuilder().UseMauiApp<App>();builder.Services.AddShinyMediator(x => x.UseMaui());// AddSingletonAsImplementedInterfaces/AddScopedAsImplementedInterfaces are extension methods we've added to IServiceCollection// that allow you to register all interfaces that a class implementsbuilder.Services.AddSingletonAsImplementedInterfaces<TestEventHandler>();builder.Services.AddSingletonAsImplementedInterfaces<TestCommandHandler>();builder.Services.AddSingletonAsImplementedInterfaces<TestResponseRequestHandler>();// OR// if you're using our attribute for source generation - simply add [RegisterHandler], [RegisterMiddleware] to your types// NOTE: that for each assembly you have source generation enabled, you will need to call AddDiscoveredMediatorHandlersFrom{AssemblyName}builder.Services.AddDiscoveredMediatorHandlersFromMaui_App();}} -
And finally, let’s use the mediator and call our new models - any model model/viewmodel/etc participating in dependency injection can now inject the mediator
public class MyViewModel(Shiny.Mediator.IMediator mediator){public async Task Execute(){await mediator.Send(new TestCommand()); // this will execute TestCommandHandlervar response = await mediator.Request(new TestResponseRequest()); // this will execute TestResponseRequestHandler and return a value// this will publish to any service registered that implement IEventHandler<TestEvent>// there are additional args here to allow you to execute values in sequentially or wait for all events to completeawait mediator.Publish(new TestEvent());}}
What about my ViewModels?
For .NET MAUI, your viewmodels have the ability to participate in the event publishing chain without being part of dependency injection
With this setup, you don’t need to worry about deallocating any events, unsubscribing from some service, or hooking to anything.
Lastly, if your page/viewmodel is navigated away from (popped), it will no longer participate in the event broadcast
-
Now…let’s go back to our MauiProgram.cs and alter the AddShinyMediator
builder.Services.AddShinyMediator(cfg => cfg.UseMaui()); -
Now your viewmodel (or page) can simply implement the IEventHandler interface to participate
public class MyViewModel : BaseViewModel,Shiny.Mediator.IEventHandler<TestEvent1>,Shiny.Mediator.IEventHandler<TestEvent2>{public async Task Handle(TestEvent @event, EventContext<TestEvent> context, CancellationToken ct){}public async Task Handle(TestEvent2 @event, EventContext<TestEvent2> context, CancellationToken ct){}}
Blazor
- Install
&
- Create your handlers just like MAUI above
- Setup Mediator with Blazor component event collection
builder.Services.AddShinyMediator(x => x.UseBlazor());
- In your main index/app.razor, add the following underneath the Blazor script
<script src="_framework/blazor.webassembly.js"></script><script src="_content/Shiny.Mediator.Blazor/Mediator.js"></script>
Source Generated Registration
When you install Shiny.Mediator, we include a source generator that will create a set of attributes that you can mark your handlers with. This will generate the registration code for you.
Those attributes are:
- SingletonHandlerAttribute
- ScopedHandlerAttribute
From there, any of those marked classes will be added to a source generated extension that you can use for you IServiceCollection registration
Example: MauiProgram.cs (ie. Project/Assembly with Shiny.Mediator installed named: Maui.App)
builder.Services.AddDiscoveredMediatorHandlersFromMaui_App();
The convention we use is AddDiscoveredMediatorHandlersFrom{AssemblyName}
- This prevents naming collisions during the registration process.
All source generated registrations will register your implementations as singleton against ALL interfaces they implement.