Skip to content

shinyorg/mediatorsample

Repository files navigation

End-To-End Shiny Mediator Sample

This shows a lot of good practices when it comes to constructing .NET MAUI applications.

Shiny Mediator

Other Libraries

Name Description
Prism The one and only .NET MVVM Framework we all know and love
Reactive Reactive Extensions for Apps
Shiny Configuration Mobile specific use-case library for Microsoft.Extensions.Configuration
SQLite The original SQLite object relational mapper
Community Toolkit MVVM modern, fast, and modular MVVM library
Settings View A beautiful looking table type control for forms
.NET MAUI Community Toolkit The premier toolkit for .NET MAUI

Reasons for this Engineering

  1. Allows cross functional teams to work enable cross functional requirements without being tightly coupled
  2. Allows each feature/module to register its own services, controls, pages, viewmodels, etc in isolation while still having access to shared functionality like logging, configuration, etc
  3. Through use of Shiny.Mediator.Prism, we can achieve strongly typed routing and navigation parameters via a simple Mediator request that implements the IPrismNavigationRequest

Dependency Graph

graph LR
    TheApp <--- Shared
    Shared --> PeopleModule
    Shared --> VehicleModule
    Shared --> OwnerModule
    OwnerModule.Contracts --> OwnerModule
    VehicleModule.Contracts --> VehicleModule
    PeopleModule.Contracts --> PeopleModule
    OwnerModule.Contracts --> Shared
    VehicleModule.Contracts --> Shared
    PeopleModule.Contracts --> Shared
    OwnerModule --> TheApp
    VehicleModule --> TheApp
    PeopleModule --> TheApp
Loading
Project Description
TheApp This is the main MAUI executable project
Shared This is where any shared services, utils, etc go to share amongst ALL modules
PeopleModule Where all the handlers, views, viewmodels, and services specific to people live
PeopleModule.Contracts Contracts that the PeopleModule owns and manages
VehicleModule Where all the handlers, views, viewmodels, and services specific to vehicles live
VehicleModule.Contracts Contracts that the VehicleModule owns and manages
OwnerModule Where all the handlers, views, viewmodels, and services specific to owners live
OwnerModule.Contracts Contracts that the OwnerModule owns and manages

FAQ

Does it offer any advantages for smaller apps?

It can. In this example, it shows how to make some navigation strongly typed for Prism. You can layer in middleware easily with Shiny Mediator. In this sample, even though it is mostly useless, the use of the cache is shown on the GetListRequestHandler's

Would I do this on a project without a large amount of team members

There are advantages to using a mediator pattern in your apps. Just like using one on the server, it allows you to break up your app as it grows over time. Where your request handlers live from the contracts, does not matter.

Why do you pass the Prism navigation service in the requests?

It allows you to pass the CURRENT contextual navigation service from your viewmodel. We do have a singleton global navigation services in Shiny Framework, but we wanted to show a safe bet on how this navigation model can work.

Did you need to use the cache for a SQLite query

Honestly, no - and you probably never should for a SQLite query. The point to note here though is that the IDataService may be calling out to a remote service. It is also a demo to show off some of what Shiny Mediator can do. Could that service do the caching? Absolutely. Should it do the caching at the service layer? That's up to you to decide!

Would you really do these cross model data linking request (ie. GetPeopleByVehicleRequest, GetVehiclesByPersonRequest) - Doesn't that cause N+1 and a lot of extra chatter?

Likely not because an app is generally single process. This shows a common pattern (and often common pitfall in server side microserving). Pick your fights & don't overengineer. Well this does