Extensions.Hosting
An Extension of the Microsoft.Extensions.Hosting library with the aim of allowing windows applications to use the hosting base.
Install / Use
/learn @reactivemarbles/Extensions.HostingREADME
NOTE: The namespacing has been changed to ReactiveMarbles.Extensions.Hosting. Please update your references to the new namespace.
ReactiveMarbles.Extensions.Hosting
Extensions for Microsoft.Extensions.Hosting that bring WPF, WinForms, WinUI, ReactiveUI, plug-ins, single-instance control, and common host utilities to desktop apps.
This repository supports both classic IHostBuilder and the newer IHostApplicationBuilder hosting model introduced in .NET 8+. Existing IHostBuilder APIs remain unchanged; equivalent IHostApplicationBuilder overloads are available where appropriate.
Supported targets include .NET Framework 4.6.2/4.8, .NET Standard 2.0, and .NET 8/9/10 (Windows where applicable).
Quick start
Choose a hosting model:
- IHostBuilder (generic host): Host.CreateDefaultBuilder(args)
- IHostApplicationBuilder (new app builder): Host.CreateApplicationBuilder(args)
Example: WPF app with IHostBuilder
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.Wpf;
var host = Host.CreateDefaultBuilder(args)
.ConfigureWpf(wpf =>
{
// Optional: register Application type and windows via the WpfBuilder
wpf.ApplicationType = typeof(App);
wpf.WindowTypes.Add(typeof(MainWindow));
wpf.ConfigureContextAction = ctx => ctx.ShutdownMode = ShutdownMode.OnMainWindowClose;
})
.UseWpfLifetime(ShutdownMode.OnMainWindowClose)
.Build();
await host.RunAsync();
Example: WPF app with IHostApplicationBuilder
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.Wpf;
var builder = Host.CreateApplicationBuilder(args)
.ConfigureWpf(wpf =>
{
wpf.ApplicationType = typeof(App);
wpf.WindowTypes.Add(typeof(MainWindow));
wpf.ConfigureContextAction = ctx => ctx.ShutdownMode = ShutdownMode.OnMainWindowClose;
})
.UseWpfLifetime(ShutdownMode.OnMainWindowClose);
await builder.Build().RunAsync();
Packages and APIs
The following sections outline the main features, their APIs for both hosting models, and example usage.
WPF (CP.Extensions.Hosting.Wpf)
Namespace: ReactiveMarbles.Extensions.Hosting.Wpf
- ConfigureWpf
- IHostBuilder ConfigureWpf(this IHostBuilder, Action<IWpfBuilder>?)
- IHostApplicationBuilder ConfigureWpf(this IHostApplicationBuilder, Action<IWpfBuilder>?)
- Use IWpfBuilder to set:
- Type? ApplicationType
- Application? Application (optional existing instance)
- IList<Type> WindowTypes
- Action<IWpfContext>? ConfigureContextAction
- UseWpfLifetime
- IHostBuilder UseWpfLifetime(this IHostBuilder, ShutdownMode = OnLastWindowClose)
- IHostApplicationBuilder UseWpfLifetime(this IHostApplicationBuilder, ShutdownMode = OnLastWindowClose)
- IWpfContext
- ShutdownMode ShutdownMode { get; set; }
- Application? WpfApplication { get; set; }
- Dispatcher Dispatcher { get; }
- bool IsLifetimeLinked { get; set; } (set internally when using UseWpfLifetime)
Example (builder model): see Quick start above.
WinForms (CP.Extensions.Hosting.WinForms)
Namespace: ReactiveMarbles.Extensions.Hosting.WinForms
- ConfigureWinForms
- IHostBuilder ConfigureWinForms(this IHostBuilder, Action<IWinFormsContext>?)
- IHostApplicationBuilder ConfigureWinForms(this IHostApplicationBuilder, Action<IWinFormsContext>?)
- ConfigureWinForms<TView>() where TView : Form
- IHostBuilder ConfigureWinForms<TView>(...)
- IHostApplicationBuilder ConfigureWinForms<TView>(...)
- Registers the main form and, if it implements IWinFormsShell, also registers it as IWinFormsShell
- ConfigureWinFormsShell<TShell>() where TShell : Form, IWinFormsShell
- IHostBuilder ConfigureWinFormsShell<TShell>()
- IHostApplicationBuilder ConfigureWinFormsShell<TShell>()
- UseWinFormsLifetime
- IHostBuilder UseWinFormsLifetime(this IHostBuilder)
- IHostApplicationBuilder UseWinFormsLifetime(this IHostApplicationBuilder)
- IWinFormsContext
- bool EnableVisualStyles { get; set; }
- Dispatcher? Dispatcher { get; set; } (WinForms dispatcher abstraction)
Example (application builder):
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.WinForms;
var builder = Host.CreateApplicationBuilder(args)
.ConfigureWinForms(ctx =>
{
ctx.EnableVisualStyles = true;
})
.ConfigureWinFormsShell<MainForm>()
.UseWinFormsLifetime();
await builder.Build().RunAsync();
WinUI (CP.Extensions.Hosting.WinUI)
Namespace: ReactiveMarbles.Extensions.Hosting.WinUI
- ConfigureWinUI<TApp, TAppWindow>() where TApp : Microsoft.UI.Xaml.Application where TAppWindow : Microsoft.UI.Xaml.Window
- IHostBuilder ConfigureWinUI<TApp, TAppWindow>()
- IHostApplicationBuilder ConfigureWinUI<TApp, TAppWindow>()
- IWinUIContext
- Window? AppWindow { get; set; }
- Type? AppWindowType { get; set; }
- DispatcherQueue? Dispatcher { get; set; }
- Application? WinUIApplication { get; set; }
Example (application builder):
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.WinUI;
var builder = Host.CreateApplicationBuilder(args)
.ConfigureWinUI<App, MainWindow>();
await builder.Build().RunAsync();
ReactiveUI integration
Namespaces: ReactiveMarbles.Extensions.Hosting.ReactiveUI (per UI stack)
- ConfigureSplatForMicrosoftDependencyResolver
- IHostBuilder ConfigureSplatForMicrosoftDependencyResolver(this IHostBuilder)
- IHostApplicationBuilder ConfigureSplatForMicrosoftDependencyResolver(this IHostApplicationBuilder)
- Variants:
- WPF: Adds WithWpf() builder stage
- WinForms: Adds WithWinForms() builder stage
- WinUI: Adds WithWinUI() builder stage
- MapSplatLocator
- IHost MapSplatLocator(this IHost host, Action<IServiceProvider?> containerFactory)
Example (WPF + ReactiveUI with application builder):
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.ReactiveUI;
using ReactiveMarbles.Extensions.Hosting.Wpf;
var builder = Host.CreateApplicationBuilder(args)
.ConfigureSplatForMicrosoftDependencyResolver()
.ConfigureWpf(wpf =>
{
wpf.ApplicationType = typeof(App);
wpf.WindowTypes.Add(typeof(MainWindow));
})
.UseWpfLifetime();
await builder.Build().RunAsync();
Plug-in system (CP.Extensions.Hosting.Plugins)
Namespace: ReactiveMarbles.Extensions.Hosting.Plugins
- ConfigurePlugins
- IHostBuilder ConfigurePlugins(this IHostBuilder, Action<IPluginBuilder?> configure)
- IHostApplicationBuilder ConfigurePlugins(this IHostApplicationBuilder, Action<IPluginBuilder?> configure)
- IPluginBuilder key options (typical):
- UseContentRoot (bool): also scan content root
- IncludeFrameworks(params string[] globs)
- IncludePlugins(params string[] globs)
- AddScanDirectories(params string[] directories)
- PluginMatcher / FrameworkMatcher (advanced globbing)
- AssemblyScanFunc: Func<Assembly, IEnumerable<IPlugin?>> for discovery
Example (application builder):
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.Plugins;
var builder = Host.CreateApplicationBuilder(args)
.ConfigurePlugins(plugins =>
{
plugins.UseContentRoot = true;
// Add framework assemblies and plugin patterns
plugins.IncludeFrameworks(@"\\netstandard2.0\\*.FrameworkLib.dll");
plugins.IncludePlugins(@"\\Plugins\\{runtime}\\ReactiveMarbles.Plugin.*.dll");
});
await builder.Build().RunAsync();
Single instance (CP.Extensions.Hosting.SingleInstance)
Namespace: ReactiveMarbles.Extensions.Hosting.AppServices
- ConfigureSingleInstance
- IHostBuilder ConfigureSingleInstance(this IHostBuilder, Action<IMutexBuilder> configure)
- IHostApplicationBuilder ConfigureSingleInstance(this IHostApplicationBuilder, Action<IMutexBuilder> configure)
- IHostBuilder ConfigureSingleInstance(this IHostBuilder, string mutexId)
- IHostApplicationBuilder ConfigureSingleInstance(this IHostApplicationBuilder, string mutexId)
- IMutexBuilder
- string MutexId { get; set; }
- Action<IHostEnvironment, ILogger>? WhenNotFirstInstance { get; set; }
Example (application builder):
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.AppServices;
var builder = Host.CreateApplicationBuilder(args)
.ConfigureSingleInstance(cfg =>
{
cfg.MutexId = "{ea031523-3a63-45e5-85f2-6fa75fbf37ed}";
cfg.WhenNotFirstInstance = (env, logger) =>
logger.LogWarning("Application {0} already running.", env.ApplicationName);
});
await builder.Build().RunAsync();
Service host utilities (CP.Extensions.Hosting.PluginService)
Namespace: ReactiveMarbles.Extensions.Hosting.PluginService
- UseServiceBaseLifetime
- IHostBuilder UseServiceBaseLifetime(this IHostBuilder)
- IHostApplicationBuilder UseServiceBaseLifetime(this IHostApplicationBuilder)
- UseConsoleLifetime (IHostApplicationBuilder only)
- IHostApplicationBuilder UseConsoleLifetime(this IHostApplicationBuilder)
- RunAsServiceAsync
- Task RunAsServiceAsync(this IHostBuilder, CancellationToken = default)
- Task RunAsServiceAsync(this HostApplicationBuilder, CancellationToken = default)
- ServiceHost
- Task Create(Type type, string[] args, Func<IHostBuilder?, IHostBuilder?>? configureHostBuilder = null, Action<IHost>? configureHost = null, string nameSpace = "ReactiveMarbles.Plugin", string? targetRuntime = null)
- Task CreateApplication(Type type, string[] args, Func<IHostApplicationBuilder?, IHostApplicationBuilder?>? configureHostBuilder = null, Action<IHost>? configureHost = null, string nameSpace = "ReactiveMarbles.Plugin", string? targetRuntime = null)
Example (service/console dual mode using IHostApplicationBuilder):
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.PluginService;
var builder = Host.CreateApplicationBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureLoggi
Related Skills
node-connect
349.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
349.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
349.7kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
