Oakrey.Applications.Base
6.0.0
dotnet add package Oakrey.Applications.Base --version 6.0.0
NuGet\Install-Package Oakrey.Applications.Base -Version 6.0.0
<PackageReference Include="Oakrey.Applications.Base" Version="6.0.0" />
<PackageVersion Include="Oakrey.Applications.Base" Version="6.0.0" />
<PackageReference Include="Oakrey.Applications.Base" />
paket add Oakrey.Applications.Base --version 6.0.0
#r "nuget: Oakrey.Applications.Base, 6.0.0"
#:package Oakrey.Applications.Base@6.0.0
#addin nuget:?package=Oakrey.Applications.Base&version=6.0.0
#tool nuget:?package=Oakrey.Applications.Base&version=6.0.0
Oakrey.Applications.Base
A foundational .NET library for building modular WPF applications. It provides application lifecycle management, structured logging and telemetry, MVVM ViewModel resolution, service preloading with error diagnostics, and a set of WPF utilities.
Main features
- Application base class �
OakreyApplicationextendsSystem.Windows.Applicationand wires up DI, logging, telemetry, and all unhandled-exception handlers in one place. - Application metadata �
IApplicationInfo/AppInfoBaseexpose name, version, log paths, settings paths, deployment URL, and application logo. - ViewModel resolution �
ViewModelProvideris a XAML markup extension that resolves ViewModels from the DI container, creates a scoped lifetime perFrameworkElement, and disposes it onUnloaded. - Service preloading �
IPreLoadablecontract with observable error propagation. Sequential (TryPreloadServices) and parallel (TryPreloadServicesParallel) strategies. Aggregates errors and shuts down gracefully if preloading fails. - Logging and telemetry � integrates
Oakrey.Log(file + WPF queue loggers) andOakrey.Telemetrytracing. Debug builds automatically lower the log threshold toTrace. - WPF behaviors and extensions �
BindableSelectedItemBehaviorfor two-way binding ofTreeView.SelectedItem;KeyboardExtensionfor detecting keyboard shortcut combinations. - Path helpers �
PathsAndNamescentralises assembly name, default settings directory, and per-user%AppData%settings path resolution.
Architecture
classDiagram
class OakreyApplication {
+IServiceProvider Services
+GetService~T~()
#App_Startup()
#AppStartup(CancellationToken) Task
#SetLoggers()
#TryPreloadServices(CancellationToken, Type[]) Task
#TryPreloadServicesParallel(CancellationToken, Type[]) Task
}
class IApplicationInfo {
+Name : string
+Version : string
+LogFilePath : FileInfo
+LogDirectoryPath : DirectoryInfo
+UserSettingsPath : string
+DefaultSettingsPath : string
+DeploymentUrl : string
+Logo : BitmapImage
}
class AppInfoBase {
<<abstract>>
}
class IPreLoadable {
<<interface>>
+Preload(CancellationToken) Task
}
class ViewModelProvider {
<<MarkupExtension>>
+ViewModelType : Type
+ProvideValue() object
}
class PreLoadingException {
+Details : string
}
OakreyApplication --> IApplicationInfo : resolves
OakreyApplication --> IPreLoadable : preloads
OakreyApplication ..> PreLoadingException : observes
AppInfoBase ..|> IApplicationInfo
IPreLoadable ..> PreLoadingException : publishes
ViewModelProvider --> IServiceProvider : resolves from
Requirements
- .NET 10 or higher
- Windows (WPF target:
net10.0-windows)
Installation
NuGet Package Manager
- Open Tools > NuGet Package Manager > Manage NuGet Packages for Solution.
- Search for
Oakrey.Applications.Baseand click Install.
.NET CLI
dotnet add package Oakrey.Applications.Base
Package Manager Console
Install-Package Oakrey.Applications.Base
Usage
1. Implement application metadata
public class MyAppInfo : AppInfoBase, IApplicationInfo
{
public override string DeploymentUrl => "https://deploy.example.com/";
}
2. Register services and subclass OakreyApplication
public partial class App : OakreyApplication
{
public App() : base(ConfigureServices) { }
private static void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IApplicationInfo, MyAppInfo>();
services.AddSingleton<WpfQueueLogger>();
// register your own services here
}
protected override async Task AppStartup(CancellationToken cancellationToken)
{
await TryPreloadServices(cancellationToken, typeof(IMyPreloadable));
Current.MainWindow = new MainWindow();
Current.MainWindow.Show();
}
}
In App.xaml set x:Class="MyApp.App" and remove the default StartupUri. Wire the startup event:
<local:App x:Class="MyApp.App"
xmlns:local="clr-namespace:MyApp"
Startup="App_Startup">
</local:App>
3. Resolve ViewModels in XAML
<Window xmlns:app="clr-namespace:Oakrey.Applications;assembly=Oakrey.Applications.Base"
DataContext="{app:ViewModelProvider viewModelType={x:Type local:MainViewModel}}">
The ViewModel is resolved from the DI container in a new scope. The scope is disposed automatically when the Window unloads.
4. Implement a preloadable service
public class MyStartupService : IPreLoadable
{
private readonly Subject<PreLoadingException> _errors = new();
public IDisposable Subscribe(IObserver<PreLoadingException> observer)
=> _errors.Subscribe(observer);
public async Task Preload(CancellationToken cancellationToken)
{
// perform startup work; publish to _errors on failure
await Task.CompletedTask;
}
}
Register it with the DI container and pass its interface to TryPreloadServices.
5. Bind TreeView selected item
<TreeView>
<i:Interaction.Behaviors>
<app:BindableSelectedItemBehavior SelectedItem="{Binding SelectedNode, Mode=TwoWay}" />
</i:Interaction.Behaviors>
</TreeView>
Configuration
| Setting | Location | Description |
|---|---|---|
| Default settings | AppInfoBase.DefaultSettingsPath |
<app base dir>/DefaultSettings.json |
| User settings | AppInfoBase.UserSettingsPath |
%AppData%/<AppName>/Settings.json |
| Log files | AppInfoBase.LogFilePath |
%LocalAppData%/<AppName>/Logs/LOG-<timestamp>.txt |
| Log threshold | LoggerFactory.GlobalThreshold |
Set to Trace automatically when a debugger is attached |
Development notes
- The library targets
net10.0-windowsand has a hard dependency on WPF; it cannot be used in non-Windows or non-WPF projects. PathsAndNamesreads from the entry assembly. In unit test hosts this may throwInvalidOperationException; mockIApplicationInfoinstead of relying onAppInfoBasedirectly in tests.- Unhandled exceptions from the UI thread,
TaskScheduler, andAppDomainare all caught, logged, and marked as handled. Override the relevant handlers in a subclass to add custom recovery logic. - The DI container is built once in the constructor and is available via
Services. CommunityToolkitIoc.Defaultis also configured during startup for XAML-friendly access.
License
MIT. Copyright (c) Oakrey 2016-present.
Repository: https://dev.azure.com/oakrey/OpenPackages/_git/ApplicationServices
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows7.0 is compatible. |
-
net10.0-windows7.0
- AsyncAwaitBestPractices (>= 10.0.0)
- CommonNet.DependencyInjection (>= 0.11.0)
- CommunityToolkit.Mvvm (>= 8.4.2)
- Microsoft.Extensions.DependencyInjection (>= 10.0.8)
- Microsoft.Xaml.Behaviors.Wpf (>= 1.1.142)
- Oakrey.Applications.About (>= 6.0.0)
- Oakrey.Applications.Abstractions (>= 6.0.0)
- Oakrey.Applications.Files (>= 6.0.0)
- Oakrey.Applications.Help (>= 6.0.0)
- Oakrey.Applications.Json (>= 6.0.0)
- Oakrey.Applications.Log (>= 6.0.0)
- Oakrey.Applications.ReportIssue (>= 6.0.0)
- Oakrey.Applications.Settings (>= 6.0.0)
- Oakrey.Applications.SplashScreen (>= 6.0.0)
- Oakrey.Applications.Telemetry (>= 2.0.6)
- Oakrey.Applications.ViewModels (>= 2.0.4)
- Oakrey.Log.Windows (>= 2.0.2)
- Oakrey.Telemetry (>= 2.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.