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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CP.Extensions.Hosting.Wpf" Version="2.2.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CP.Extensions.Hosting.Wpf" Version="2.2.2" />
                    
Directory.Packages.props
<PackageReference Include="CP.Extensions.Hosting.Wpf" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CP.Extensions.Hosting.Wpf --version 2.2.2
                    
#r "nuget: CP.Extensions.Hosting.Wpf, 2.2.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CP.Extensions.Hosting.Wpf@2.2.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CP.Extensions.Hosting.Wpf&version=2.2.2
                    
Install as a Cake Addin
#tool nuget:?package=CP.Extensions.Hosting.Wpf&version=2.2.2
                    
Install as a Cake Tool

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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