Quick Start
Quick Start
-
First, let’s create our request & event handlers
using Shiny.Mediator;public record TestRequest(string AnyArgs, int YouWant) : IRequest;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 a RequestHandler. 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 RequestHandler
using Shiny.Mediator;// NOTE: Request handlers are registered as singletonspublic class TestRequestHandler : IRequestHandler<TestRequest>{// you can do all dependency injection herepublic async Task Handle(TestRequest request, CancellationToken ct){// do something async here}}public class TestResponseRequestHandler : IRequestHandler<TestResponseRequest, TestResponse>{public async Task<TestResponse> Handle(TestResponseRequest request, 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();// 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<TestRequestHandler>();builder.Services.AddSingltonAsImplementedInterfaces<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 TestRequest()); // this will execute TestRequestHandlervar 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, CancellationToken ct){}public async Task Handle(TestEvent2 @event, CancellationToken ct){}}
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 request handlers, event handlers, and middleware with. This will generate the registration code for you.
Those attributes are:
- SingletonHandlerAttribute
- ScopedHandlerAttribute
- SingletonMiddlewareAttribute
- ScopedMiddlewareAttribute
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.