Extendable View Model
Overview
ExtendableViewModel<TSelfInterface> is a generic abstract class that extends RoutableViewModel and adds support for dynamic extensibility. It allows your view model to be extended with additional features.
How It Works
The
IExtensionServicediscovers registered implementations ofIExtensionFor<TSelfInterface>from the DI container.Each extension's
Extendmethod is invoked, passing your view model and its disposable container.AfterLoadExtensionsis called to allow for any final setup in your view model.
Extensions are loaded on the UI thread (via Dispatcher.UIThread.Post) to avoid deadlocks.
Core Components
Generic Parameter
The TSelfInterface generic parameter specifies the interface that your view model implements (or the view model type itself).
IExtensionFor Interface
Your extensions should implement the IExtensionFor<in T> interface, which contains a single method:
This method is called when the extended view model is initialized.
context: Represents the view model itself.contextDispose: The CompositeDisposable container of the view model.
You can register your IDisposable objects with it. Additionally, if your extension class implements IDisposable, the view model will automatically register it to the CompositeDisposable.
Extension Registration
Each extension is registered through the Extensions builder available on the application host builder. Registration can happen in any place that has access to the builder — Program.cs, a dedicated module, a plugin entry point, etc.
This registers MyHomePageExtension as a transient service implementing IExtensionFor<IHomePage> in the IServiceCollection. At runtime the DI container resolves all registered IExtensionFor<IHomePage> implementations and applies them to every IHomePage instance.
Initialization and Loading
Extensions are loaded automatically in the constructor of ExtendableViewModel via the IExtensionService. The service resolves all registered IExtensionFor<TSelfInterface> implementations and calls their Extend method.
You must implement the abstract AfterLoadExtensions method to perform any initialization required after extensions are loaded:
You can leave this method empty if no post-initialization logic is needed.
Example
A basic usage example is our Home Page. When adding pages to an app using Asv.Avalonia, you will likely create an Extension for IHomePage so your page is accessible from the home tools menu.
These extensions look like this:
In this example, we add a new tool to the home page that opens the LogViewer page. We export an extension for the IHomePage interface, which is implemented by HomePageViewModel. The interface contains the Tools collection, which we modify.
API
ExtendableViewModel<TSelfInterface>
Represents a base class for a view model that supports extensibility via the IExtensionService. This class provides a mechanism to load and apply extensions dynamically.
Method | Return Type | Description |
|---|---|---|
|
| Gets the current instance as |
|
| Called after all extensions have been loaded and applied. Derived classes must implement this method to provide additional logic after extension loading. |