What is a Service?
Overview
In Asv.Avalonia, a Service is a specialized, usually singleton component that provides shared logic and infrastructure across the entire application. While ViewModels handle the logic for specific UI pieces, Services handle "global" concerns that don't belong to any single view.
Core Concept
Services are the backbone of your application's infrastructure. They are designed to be:
Singletons: Most services exist as a single instance throughout the application's lifecycle.
Decoupled: They don't know about the UI (Views). They provide data or functionality that ViewModels can consume.
Injected: Services are managed by the IServiceCollection container and are injected into other components via constructors.
Key Characteristics
1. Lifecycle Management
Services can inherit from AsyncDisposableOnce. This allows them to perform asynchronous cleanup when the application shuts down, such as closing database connections or saving state.
2. Global State
Services are the perfect place to store state that needs to persist as the user navigates between pages. For example, the NavigationService keeps track of the navigation history, and the ThemeService remembers whether the user prefers Dark or Light mode.
3. Configuration
Some services need settings. By inheriting from ServiceWithConfigBase<TConfig>, a service automatically gains the ability to load and save its state using the framework's configuration system. See our LocalizationService for the example.
Common Built-in Services
The framework provides several essential services out of the box. For example:
Navigation Service: Manages page switching, back/forward history, and focus tracking.
Command Service: Centralizes command execution, global hotkeys, and Undo/Redo history.
Localization Service: Manages language switching and string translations.
Theme Service: Controls the visual appearance (Dark/Light themes, accent colors).
When to Create a Service?
You should consider creating a service when you have logic that:
Needs to be accessed from multiple ViewModels.
Manages a global resource (e.g., a hardware connection, a database, or a web API).
Needs to stay alive even when the current page is closed.
Handles cross-cutting concerns like logging, caching, or user preferences.
How to Define a Service
A typical service consists of an interface and an implementation:
To use it, simply request it in a constructor:
Service Registration
Services are registered explicitly in the builder chain using the standard .NET IServiceCollection API. This can be done anywhere that has access to the builder — directly in Program.cs or, more commonly, inside a mixin extension method for your module (see Registration via Mixin below).
Standard Registration
The full list of registration methods and their semantics is covered in the official docs; below are the lifetimes used in this framework:
Method | Lifetime | Typical use in this framework |
|---|---|---|
| One instance for the whole app | Services (navigation, theme, commands, …) |
| New instance every time it is requested | Extensions ( |
| New instance per key per request | Views (ViewLocator), keyed extensions |
Registration via Mixin (Recommended for Modules)
For better organization, create an extension method (mixin) for your module:
Then use it in Program.cs:
Conditional Registration
Sometimes a service should only be registered under specific conditions. Simply use standard if checks when registering: