Module system
Purpose
Explain how Mnemo discovers and loads feature modules: routes, sidebar entries, DI, translations, AI tools, widgets, and keybind manifests—without hard-coding every feature in one startup file.
Code location
- Contract:
Mnemo.Core/Services/IModule.cs - Discovery + orchestration:
Mnemo.UI/Services/Bootstrapper.cs(DiscoverModules, module loops) - Implementations:
Mnemo.UI/Modules/**/*.cs(e.g.NotesModule,MindmapModule,CoreUIModule)
Key concepts
| Concept | Meaning |
|---|---|
| Module contract | IModule — feature package entry point |
| Auto-discovery | Reflection scan for assignable types in loaded Mnemo.* assemblies |
| DI registration | ConfigureServices(IServiceRegistrar) adds VMs/services |
| Navigation integration | RegisterRoutes(INavigationRegistry) maps route keys → view model types |
| Sidebar integration | RegisterSidebarItems(ISidebarService) supplies icons, order, grouping |
| AI tools / widgets | RegisterTools, RegisterWidgets after IServiceProvider exists |
Main interfaces / classes
// Mnemo.Core/Services/IModule.cs (conceptual summary)
public interface IModule
{
void ConfigureServices(IServiceRegistrar services);
void RegisterTranslationSources(ITranslationSourceRegistry registry);
void RegisterRoutes(INavigationRegistry registry);
void RegisterSidebarItems(ISidebarService sidebarService);
void RegisterTools(IFunctionRegistry registry, IServiceProvider services);
void RegisterWidgets(IWidgetRegistry registry, IServiceProvider services);
void RegisterKeybindManifest(IKeybindManifestRegistry registry);
}
Reference implementation pattern: Mnemo.UI/Modules/Notes/NotesModule.cs.
Lifecycle
- App starts →
Bootstrapper.Build(). - Core/Infrastructure/UI shell services register.
DiscoverModules()collectsIModuleinstances.RegisterTranslationSources→ localization provider registers.ConfigureServicesfor each module → VMs/providers available at resolve time.RegisterKeybindManifestaggregates chords.BuildServiceProvider().RegisterRoutes,RegisterSidebarItems,RegisterTools,RegisterWidgets.- UI shows
MainWindow;NavigationServicedrives workspace VM from route IDs.
Adding a new module
- Create
Mnemo.UI/Modules/YourFeature/YourFeatureModule.csimplementingIModule(public class, parameterless ctor). ConfigureServices:AddTransientfor view models; registerISearchProvideror other interfaces if the feature participates in global search.RegisterTranslationSources: embed JSON resources if localized strings live with the module (seeNotesModule).RegisterRoutes:registry.RegisterRoute("your-route", typeof(YourViewModel))— key must stay stable for deep links and navigation statistics.RegisterSidebarItems: supply localized title key, route id,avares://icon path, section name, sort order.RegisterTools: optional—delegate to a registrar class pattern (NotesToolRegistrar) to keep module lean.RegisterWidgets: optional dashboard tiles.RegisterKeybindManifest: optional static chord declarations for user-editable binds.- Build—discovery picks up any new
IModuleinMnemo.UIassembly automatically.
Gotchas
- Silent ctor failures: exceptions inside
Activator.CreateInstanceare swallowed during discovery—your module simply never loads. - Order: route IDs must not collide; last registration wins depends on registry implementation—avoid duplicate keys.
- Sidebar vs routes: mismatch between sidebar
routeargument andRegisterRoutekey breaks navigation clicks. - Plugins: comment in
DiscoverModulesmentions loading plugin assemblies intoAppDomainbefore scan—external modules must be loaded early enough to appear in assembly set.
Related: Startup flow, UI