CP.Extensions.Hosting.Wpf
2.2.2
dotnet add package CP.Extensions.Hosting.Wpf --version 2.2.2
NuGet\Install-Package CP.Extensions.Hosting.Wpf -Version 2.2.2
<PackageReference Include="CP.Extensions.Hosting.Wpf" Version="2.2.2" />
<PackageVersion Include="CP.Extensions.Hosting.Wpf" Version="2.2.2" />
<PackageReference Include="CP.Extensions.Hosting.Wpf" />
paket add CP.Extensions.Hosting.Wpf --version 2.2.2
#r "nuget: CP.Extensions.Hosting.Wpf, 2.2.2"
#:package CP.Extensions.Hosting.Wpf@2.2.2
#addin nuget:?package=CP.Extensions.Hosting.Wpf&version=2.2.2
#tool nuget:?package=CP.Extensions.Hosting.Wpf&version=2.2.2
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 (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())
.ConfigureLogging()
.ConfigureConfiguration(args)
.UseConsoleLifetime(); // or .UseServiceBaseLifetime() for Windows Service
await builder.Build().RunAsync();
Example (helper):
using ReactiveMarbles.Extensions.Hosting.PluginService;
await ServiceHost.CreateApplication(
typeof(Program),
args,
hb => hb // external builder customization
.ConfigurePlugins(pb => { /* plugin globs */ }),
host => { /* use host.Services */ },
nameSpace: "ReactiveMarbles.Plugin");
Identity + Entity Framework Core
Namespaces:
- ReactiveMarbles.Extensions.Hosting.Identity.EntityFrameworkCore (SqlServer)
- ReactiveMarbles.Extensions.Hosting.Identity.EntityFrameworkCore.Sqlite (Sqlite)
APIs (service collection extensions used inside UseWebHostServices):
- IServiceCollection UseEntityFrameworkCoreSqlServer<TContext, TUser, TRole>(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)
- IServiceCollection UseEntityFrameworkCoreSqlServer<TContext, TUser>(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)
- IServiceCollection UseEntityFrameworkCoreSqlite<TContext, TUser, TRole>(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)
- IServiceCollection UseEntityFrameworkCoreSqlite<TContext, TUser>(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)
Host/web host wiring:
- IHostBuilder UseWebHostServices(this IHostBuilder, Action<WebHostBuilderContext, IServiceCollection> configureServices, bool validateScopes = false)
- IHostBuilder UseWebHostServices(this IHostBuilder, Action<WebHostBuilderContext, IServiceCollection> configureServices, Func<IWebHostBuilder, IWebHostBuilder> configureWebHost, bool validateScopes = false)
- IHostBuilder UseWebHostServices(this IHostBuilder, Action<WebHostBuilderContext, IServiceCollection> configureServices, Func<IWebHostBuilder, IWebHostBuilder> configureWebHost, Func<IApplicationBuilder, IApplicationBuilder> configureApp, bool validateScopes = false)
Example:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ReactiveMarbles.Extensions.Hosting.Identity.EntityFrameworkCore;
var host = Host.CreateDefaultBuilder(args)
.UseWebHostServices((whb, services) =>
{
services.UseEntityFrameworkCoreSqlServer<AppDbContext, IdentityUser, IdentityRole>(whb, "DefaultConnection");
})
.Build();
await host.RunAsync();
Reactive examples
- WPF + ReactiveUI + Single instance:
var builder = Host.CreateApplicationBuilder(args)
.ConfigureSplatForMicrosoftDependencyResolver()
.ConfigureWpf(wpf =>
{
wpf.ApplicationType = typeof(App);
wpf.WindowTypes.Add(typeof(MainWindow));
})
.UseWpfLifetime()
.ConfigureSingleInstance("{ea031523-3a63-45e5-85f2-6fa75fbf37ed}");
await builder.Build().RunAsync();
Notes
- WPF/WinForms/WinUI components target Windows only.
- When using IHostApplicationBuilder, prefer chaining extension methods that return IHostApplicationBuilder so you can call Build() on the final HostApplicationBuilder instance.
- Plugin scanning uses glob patterns. Ensure your plugin folders are copied to output and the patterns match your runtime folder (e.g., Plugins\net9.0-windows\Your.Plugin.*.dll).
Legacy snippets (IHostBuilder only)
ReactiveMarbles.Extensions.Hosting.Plugins
.ConfigurePlugins(pluginBuilder =>
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Running using dotNet {0}", Environment.Version);
var process = Process.GetCurrentProcess();
var fullPath = process.MainModule?.FileName?.Replace(process.MainModule.ModuleName!, string.Empty);
Console.WriteLine("Add Scan Directories: {0}", fullPath);
pluginBuilder?.AddScanDirectories(fullPath!);
pluginBuilder?.IncludeFrameworks(@"\netstandard2.0\*.FrameworkLib.dll");
var runtime = Path.GetFileName(AppContext.BaseDirectory);
Console.WriteLine(@"Include Plugins from: \Plugins\{0}\{1}*.dll", runtime, "ReactiveMarbles.Plugin");
pluginBuilder?.IncludePlugins(@$"\Plugins\{runtime}\{{YourPluginNamespace}}*.dll");
Console.ResetColor();
})
ReactiveMarbles.Extensions.Hosting.PluginService
await ServiceHost.Create(
typeof(Program),
args,
hb => hb, // Configure the HostBuilder
host => {}, // Configure the Host
nameSpace: "ReactiveMarbles.Plugin").ConfigureAwait(false);
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0-windows7.0 is compatible. net9.0-windows was computed. net9.0-windows7.0 is compatible. net10.0-windows was computed. |
.NET Framework | net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
-
.NETFramework 4.6.2
- CP.Extensions.Hosting.MainUIThread (>= 2.2.2)
-
net8.0-windows7.0
- CP.Extensions.Hosting.MainUIThread (>= 2.2.2)
-
net9.0-windows7.0
- CP.Extensions.Hosting.MainUIThread (>= 2.2.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on CP.Extensions.Hosting.Wpf:
Package | Downloads |
---|---|
CP.Extensions.Hosting.ReactiveUI.Wpf
This extension adds ReactiveUI support to generic host based dotnet core 8.0 / 9.0 WPF applications. With this you can enhance your application with a UI, and use all the services provided by the generic host like DI, logging etc, together with this reactive MVVM framework. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
2.2.2 | 67 | 9/10/2025 |
2.1.13 | 939 | 4/29/2025 |
2.1.10 | 197 | 3/16/2025 |
2.1.8 | 183 | 2/19/2025 |
2.1.6 | 130 | 2/9/2025 |
2.1.4 | 196 | 11/21/2024 |
2.0.5 | 378 | 5/18/2024 |
1.5.2 | 135 | 5/17/2024 |
1.4.2 | 176 | 5/5/2024 |
1.3.13 | 159 | 5/1/2024 |
1.3.2 | 238 | 4/11/2024 |
1.2.2 | 226 | 3/26/2024 |
1.1.90 | 197 | 3/19/2024 |
1.1.28 | 250 | 2/5/2024 |
1.1.18 | 276 | 1/4/2024 |
1.1.11 | 161 | 12/23/2023 |
1.1.10 | 161 | 12/23/2023 |
1.1.7 | 180 | 12/14/2023 |
1.1.5 | 264 | 11/23/2023 |
1.1.3 | 162 | 11/12/2023 |
1.0.61 | 177 | 11/6/2023 |
1.0.60 | 157 | 11/6/2023 |
1.0.58 | 187 | 10/27/2023 |
1.0.56 | 185 | 10/27/2023 |
1.0.55 | 176 | 10/27/2023 |
1.0.54 | 170 | 10/27/2023 |
1.0.52 | 181 | 10/17/2023 |
1.0.50 | 172 | 10/17/2023 |
1.0.48 | 180 | 10/16/2023 |
1.0.47 | 161 | 10/16/2023 |
1.0.46 | 164 | 10/16/2023 |
1.0.44 | 166 | 10/3/2023 |
1.0.43 | 194 | 10/2/2023 |
1.0.39 | 175 | 10/2/2023 |
1.0.37 | 172 | 9/30/2023 |
1.0.33 | 181 | 9/19/2023 |
1.0.31 | 155 | 9/19/2023 |
1.0.29 | 203 | 9/14/2023 |
1.0.17 | 199 | 8/31/2023 |
1.0.15 | 199 | 8/30/2023 |
1.0.13 | 220 | 8/30/2023 |
1.0.8 | 246 | 8/1/2023 |
1.0.7 | 216 | 8/1/2023 |
1.0.6 | 245 | 7/25/2023 |
1.0.4 | 208 | 7/25/2023 |
Compatability with Net 8 / 9 and net462