{"id":24569415,"url":"https://github.com/reactivemarbles/Extensions.Hosting","last_synced_at":"2025-10-04T19:32:02.107Z","repository":{"id":183702659,"uuid":"670360196","full_name":"reactivemarbles/Extensions.Hosting","owner":"reactivemarbles","description":"An Extension of the Microsoft.Extensions.Hosting library with the aim of allowing windows applications to use the hosting base. ","archived":false,"fork":false,"pushed_at":"2024-05-18T13:20:45.000Z","size":929,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-30T00:11:05.503Z","etag":null,"topics":["extensions","hosting","microsoft","plugin","reactiveui","service","winforms","winui","wpf"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reactivemarbles.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"reactivemarbles"}},"created_at":"2023-07-24T22:03:10.000Z","updated_at":"2024-09-28T06:39:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"b601362c-536d-4e3c-8be6-162dd57174e5","html_url":"https://github.com/reactivemarbles/Extensions.Hosting","commit_stats":{"total_commits":145,"total_committers":3,"mean_commits":"48.333333333333336","dds":0.5241379310344827,"last_synced_commit":"48b5d3437dd652214f1b2e79354423e2733be225"},"previous_names":["chrispulman/cp.extensions.hosting","reactivemarbles/extensions.hosting"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivemarbles%2FExtensions.Hosting","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivemarbles%2FExtensions.Hosting/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivemarbles%2FExtensions.Hosting/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivemarbles%2FExtensions.Hosting/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reactivemarbles","download_url":"https://codeload.github.com/reactivemarbles/Extensions.Hosting/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234892310,"owners_count":18902904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["extensions","hosting","microsoft","plugin","reactiveui","service","winforms","winui","wpf"],"created_at":"2025-01-23T15:23:09.578Z","updated_at":"2025-10-04T19:32:02.094Z","avatar_url":"https://github.com/reactivemarbles.png","language":"C#","readme":"NOTE: The namespacing has been changed to ReactiveMarbles.Extensions.Hosting. Please update your references to the new namespace.\n\n# ReactiveMarbles.Extensions.Hosting\nExtensions for Microsoft.Extensions.Hosting that bring WPF, WinForms, WinUI, ReactiveUI, plug-ins, single-instance control, and common host utilities to desktop apps.\n\nThis 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.\n\nSupported targets include .NET Framework 4.6.2/4.8, .NET Standard 2.0, and .NET 8/9 (Windows where applicable).\n\n## Quick start\n\nChoose a hosting model:\n- IHostBuilder (generic host): Host.CreateDefaultBuilder(args)\n- IHostApplicationBuilder (new app builder): Host.CreateApplicationBuilder(args)\n\n### Example: WPF app with IHostBuilder\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.Wpf;\n\nvar host = Host.CreateDefaultBuilder(args)\n    .ConfigureWpf(wpf =\u003e\n    {\n        // Optional: register Application type and windows via the WpfBuilder\n        wpf.ApplicationType = typeof(App);\n        wpf.WindowTypes.Add(typeof(MainWindow));\n        wpf.ConfigureContextAction = ctx =\u003e ctx.ShutdownMode = ShutdownMode.OnMainWindowClose;\n    })\n    .UseWpfLifetime(ShutdownMode.OnMainWindowClose)\n    .Build();\n\nawait host.RunAsync();\n```\n\n### Example: WPF app with IHostApplicationBuilder\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.Wpf;\n\nvar builder = Host.CreateApplicationBuilder(args)\n    .ConfigureWpf(wpf =\u003e\n    {\n        wpf.ApplicationType = typeof(App);\n        wpf.WindowTypes.Add(typeof(MainWindow));\n        wpf.ConfigureContextAction = ctx =\u003e ctx.ShutdownMode = ShutdownMode.OnMainWindowClose;\n    })\n    .UseWpfLifetime(ShutdownMode.OnMainWindowClose);\n\nawait builder.Build().RunAsync();\n```\n\n---\n\n## Packages and APIs\nThe following sections outline the main features, their APIs for both hosting models, and example usage.\n\n### WPF (CP.Extensions.Hosting.Wpf)\nNamespace: ReactiveMarbles.Extensions.Hosting.Wpf\n- ConfigureWpf\n  - IHostBuilder ConfigureWpf(this IHostBuilder, Action\u003cIWpfBuilder\u003e?)\n  - IHostApplicationBuilder ConfigureWpf(this IHostApplicationBuilder, Action\u003cIWpfBuilder\u003e?)\n  - Use IWpfBuilder to set:\n    - Type? ApplicationType\n    - Application? Application (optional existing instance)\n    - IList\u003cType\u003e WindowTypes\n    - Action\u003cIWpfContext\u003e? ConfigureContextAction\n- UseWpfLifetime\n  - IHostBuilder UseWpfLifetime(this IHostBuilder, ShutdownMode = OnLastWindowClose)\n  - IHostApplicationBuilder UseWpfLifetime(this IHostApplicationBuilder, ShutdownMode = OnLastWindowClose)\n- IWpfContext\n  - ShutdownMode ShutdownMode { get; set; }\n  - Application? WpfApplication { get; set; }\n  - Dispatcher Dispatcher { get; }\n  - bool IsLifetimeLinked { get; set; } (set internally when using UseWpfLifetime)\n\nExample (builder model): see Quick start above.\n\n### WinForms (CP.Extensions.Hosting.WinForms)\nNamespace: ReactiveMarbles.Extensions.Hosting.WinForms\n- ConfigureWinForms\n  - IHostBuilder ConfigureWinForms(this IHostBuilder, Action\u003cIWinFormsContext\u003e?)\n  - IHostApplicationBuilder ConfigureWinForms(this IHostApplicationBuilder, Action\u003cIWinFormsContext\u003e?)\n- ConfigureWinForms\u003cTView\u003e() where TView : Form\n  - IHostBuilder ConfigureWinForms\u003cTView\u003e(...)\n  - IHostApplicationBuilder ConfigureWinForms\u003cTView\u003e(...)\n  - Registers the main form and, if it implements IWinFormsShell, also registers it as IWinFormsShell\n- ConfigureWinFormsShell\u003cTShell\u003e() where TShell : Form, IWinFormsShell\n  - IHostBuilder ConfigureWinFormsShell\u003cTShell\u003e()\n  - IHostApplicationBuilder ConfigureWinFormsShell\u003cTShell\u003e()\n- UseWinFormsLifetime\n  - IHostBuilder UseWinFormsLifetime(this IHostBuilder)\n  - IHostApplicationBuilder UseWinFormsLifetime(this IHostApplicationBuilder)\n- IWinFormsContext\n  - bool EnableVisualStyles { get; set; }\n  - Dispatcher? Dispatcher { get; set; } (WinForms dispatcher abstraction)\n\nExample (application builder):\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.WinForms;\n\nvar builder = Host.CreateApplicationBuilder(args)\n    .ConfigureWinForms(ctx =\u003e\n    {\n        ctx.EnableVisualStyles = true;\n    })\n    .ConfigureWinFormsShell\u003cMainForm\u003e()\n    .UseWinFormsLifetime();\n\nawait builder.Build().RunAsync();\n```\n\n### WinUI (CP.Extensions.Hosting.WinUI)\nNamespace: ReactiveMarbles.Extensions.Hosting.WinUI\n- ConfigureWinUI\u003cTApp, TAppWindow\u003e() where TApp : Microsoft.UI.Xaml.Application where TAppWindow : Microsoft.UI.Xaml.Window\n  - IHostBuilder ConfigureWinUI\u003cTApp, TAppWindow\u003e()\n  - IHostApplicationBuilder ConfigureWinUI\u003cTApp, TAppWindow\u003e()\n- IWinUIContext\n  - Window? AppWindow { get; set; }\n  - Type? AppWindowType { get; set; }\n  - DispatcherQueue? Dispatcher { get; set; }\n  - Application? WinUIApplication { get; set; }\n\nExample (application builder):\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.WinUI;\n\nvar builder = Host.CreateApplicationBuilder(args)\n    .ConfigureWinUI\u003cApp, MainWindow\u003e();\n\nawait builder.Build().RunAsync();\n```\n\n### ReactiveUI integration\nNamespaces: ReactiveMarbles.Extensions.Hosting.ReactiveUI (per UI stack)\n- ConfigureSplatForMicrosoftDependencyResolver\n  - IHostBuilder ConfigureSplatForMicrosoftDependencyResolver(this IHostBuilder)\n  - IHostApplicationBuilder ConfigureSplatForMicrosoftDependencyResolver(this IHostApplicationBuilder)\n- Variants:\n  - WPF: Adds WithWpf() builder stage\n  - WinForms: Adds WithWinForms() builder stage\n  - WinUI: Adds WithWinUI() builder stage\n- MapSplatLocator\n  - IHost MapSplatLocator(this IHost host, Action\u003cIServiceProvider?\u003e containerFactory)\n\nExample (WPF + ReactiveUI with application builder):\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.ReactiveUI;\nusing ReactiveMarbles.Extensions.Hosting.Wpf;\n\nvar builder = Host.CreateApplicationBuilder(args)\n    .ConfigureSplatForMicrosoftDependencyResolver()\n    .ConfigureWpf(wpf =\u003e\n    {\n        wpf.ApplicationType = typeof(App);\n        wpf.WindowTypes.Add(typeof(MainWindow));\n    })\n    .UseWpfLifetime();\n\nawait builder.Build().RunAsync();\n```\n\n### Plug-in system (CP.Extensions.Hosting.Plugins)\nNamespace: ReactiveMarbles.Extensions.Hosting.Plugins\n- ConfigurePlugins\n  - IHostBuilder ConfigurePlugins(this IHostBuilder, Action\u003cIPluginBuilder?\u003e configure)\n  - IHostApplicationBuilder ConfigurePlugins(this IHostApplicationBuilder, Action\u003cIPluginBuilder?\u003e configure)\n- IPluginBuilder key options (typical):\n  - UseContentRoot (bool): also scan content root\n  - IncludeFrameworks(params string[] globs)\n  - IncludePlugins(params string[] globs)\n  - AddScanDirectories(params string[] directories)\n  - PluginMatcher / FrameworkMatcher (advanced globbing)\n  - AssemblyScanFunc: Func\u003cAssembly, IEnumerable\u003cIPlugin?\u003e\u003e for discovery\n\nExample (application builder):\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.Plugins;\n\nvar builder = Host.CreateApplicationBuilder(args)\n    .ConfigurePlugins(plugins =\u003e\n    {\n        plugins.UseContentRoot = true;\n        // Add framework assemblies and plugin patterns\n        plugins.IncludeFrameworks(@\"\\\\netstandard2.0\\\\*.FrameworkLib.dll\");\n        plugins.IncludePlugins(@\"\\\\Plugins\\\\{runtime}\\\\ReactiveMarbles.Plugin.*.dll\");\n    });\n\nawait builder.Build().RunAsync();\n```\n\n### Single instance (CP.Extensions.Hosting.SingleInstance)\nNamespace: ReactiveMarbles.Extensions.Hosting.AppServices\n- ConfigureSingleInstance\n  - IHostBuilder ConfigureSingleInstance(this IHostBuilder, Action\u003cIMutexBuilder\u003e configure)\n  - IHostApplicationBuilder ConfigureSingleInstance(this IHostApplicationBuilder, Action\u003cIMutexBuilder\u003e configure)\n  - IHostBuilder ConfigureSingleInstance(this IHostBuilder, string mutexId)\n  - IHostApplicationBuilder ConfigureSingleInstance(this IHostApplicationBuilder, string mutexId)\n- IMutexBuilder\n  - string MutexId { get; set; }\n  - Action\u003cIHostEnvironment, ILogger\u003e? WhenNotFirstInstance { get; set; }\n\nExample (application builder):\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.AppServices;\n\nvar builder = Host.CreateApplicationBuilder(args)\n    .ConfigureSingleInstance(cfg =\u003e\n    {\n        cfg.MutexId = \"{ea031523-3a63-45e5-85f2-6fa75fbf37ed}\";\n        cfg.WhenNotFirstInstance = (env, logger) =\u003e\n            logger.LogWarning(\"Application {0} already running.\", env.ApplicationName);\n    });\n\nawait builder.Build().RunAsync();\n```\n\n### Service host utilities (CP.Extensions.Hosting.PluginService)\nNamespace: ReactiveMarbles.Extensions.Hosting.PluginService\n- UseServiceBaseLifetime\n  - IHostBuilder UseServiceBaseLifetime(this IHostBuilder)\n  - IHostApplicationBuilder UseServiceBaseLifetime(this IHostApplicationBuilder)\n- UseConsoleLifetime (IHostApplicationBuilder only)\n  - IHostApplicationBuilder UseConsoleLifetime(this IHostApplicationBuilder)\n- RunAsServiceAsync\n  - Task RunAsServiceAsync(this IHostBuilder, CancellationToken = default)\n  - Task RunAsServiceAsync(this HostApplicationBuilder, CancellationToken = default)\n- ServiceHost\n  - Task Create(Type type, string[] args, Func\u003cIHostBuilder?, IHostBuilder?\u003e? configureHostBuilder = null, Action\u003cIHost\u003e? configureHost = null, string nameSpace = \"ReactiveMarbles.Plugin\", string? targetRuntime = null)\n  - Task CreateApplication(Type type, string[] args, Func\u003cIHostApplicationBuilder?, IHostApplicationBuilder?\u003e? configureHostBuilder = null, Action\u003cIHost\u003e? configureHost = null, string nameSpace = \"ReactiveMarbles.Plugin\", string? targetRuntime = null)\n\nExample (service/console dual mode using IHostApplicationBuilder):\n```csharp\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.PluginService;\n\nvar builder = Host.CreateApplicationBuilder(args)\n    .UseContentRoot(Directory.GetCurrentDirectory())\n    .ConfigureLogging()\n    .ConfigureConfiguration(args)\n    .UseConsoleLifetime(); // or .UseServiceBaseLifetime() for Windows Service\n\nawait builder.Build().RunAsync();\n```\n\nExample (helper):\n```csharp\nusing ReactiveMarbles.Extensions.Hosting.PluginService;\n\nawait ServiceHost.CreateApplication(\n    typeof(Program),\n    args,\n    hb =\u003e hb // external builder customization\n            .ConfigurePlugins(pb =\u003e { /* plugin globs */ }),\n    host =\u003e { /* use host.Services */ },\n    nameSpace: \"ReactiveMarbles.Plugin\");\n```\n\n### Identity + Entity Framework Core\nNamespaces:\n- ReactiveMarbles.Extensions.Hosting.Identity.EntityFrameworkCore (SqlServer)\n- ReactiveMarbles.Extensions.Hosting.Identity.EntityFrameworkCore.Sqlite (Sqlite)\n\nAPIs (service collection extensions used inside UseWebHostServices):\n- IServiceCollection UseEntityFrameworkCoreSqlServer\u003cTContext, TUser, TRole\u003e(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)\n- IServiceCollection UseEntityFrameworkCoreSqlServer\u003cTContext, TUser\u003e(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)\n- IServiceCollection UseEntityFrameworkCoreSqlite\u003cTContext, TUser, TRole\u003e(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)\n- IServiceCollection UseEntityFrameworkCoreSqlite\u003cTContext, TUser\u003e(WebHostBuilderContext, string connectionStringName, ServiceLifetime = Scoped)\n\nHost/web host wiring:\n- IHostBuilder UseWebHostServices(this IHostBuilder, Action\u003cWebHostBuilderContext, IServiceCollection\u003e configureServices, bool validateScopes = false)\n- IHostBuilder UseWebHostServices(this IHostBuilder, Action\u003cWebHostBuilderContext, IServiceCollection\u003e configureServices, Func\u003cIWebHostBuilder, IWebHostBuilder\u003e configureWebHost, bool validateScopes = false)\n- IHostBuilder UseWebHostServices(this IHostBuilder, Action\u003cWebHostBuilderContext, IServiceCollection\u003e configureServices, Func\u003cIWebHostBuilder, IWebHostBuilder\u003e configureWebHost, Func\u003cIApplicationBuilder, IApplicationBuilder\u003e configureApp, bool validateScopes = false)\n\nExample:\n```csharp\nusing Microsoft.AspNetCore.Identity;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\nusing ReactiveMarbles.Extensions.Hosting.Identity.EntityFrameworkCore;\n\nvar host = Host.CreateDefaultBuilder(args)\n    .UseWebHostServices((whb, services) =\u003e\n    {\n        services.UseEntityFrameworkCoreSqlServer\u003cAppDbContext, IdentityUser, IdentityRole\u003e(whb, \"DefaultConnection\");\n    })\n    .Build();\n\nawait host.RunAsync();\n```\n\n### Reactive examples\n- WPF + ReactiveUI + Single instance:\n```csharp\nvar builder = Host.CreateApplicationBuilder(args)\n    .ConfigureSplatForMicrosoftDependencyResolver()\n    .ConfigureWpf(wpf =\u003e\n    {\n        wpf.ApplicationType = typeof(App);\n        wpf.WindowTypes.Add(typeof(MainWindow));\n    })\n    .UseWpfLifetime()\n    .ConfigureSingleInstance(\"{ea031523-3a63-45e5-85f2-6fa75fbf37ed}\");\n\nawait builder.Build().RunAsync();\n```\n\n### Notes\n- WPF/WinForms/WinUI components target Windows only.\n- When using IHostApplicationBuilder, prefer chaining extension methods that return IHostApplicationBuilder so you can call Build() on the final HostApplicationBuilder instance.\n- 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).\n\n---\n\n## Legacy snippets (IHostBuilder only)\n\n#### ReactiveMarbles.Extensions.Hosting.Plugins\n```csharp\n.ConfigurePlugins(pluginBuilder =\u003e\n{\n    Console.ForegroundColor = ConsoleColor.Yellow;\n    Console.WriteLine(\"Running using dotNet {0}\", Environment.Version);\n\n    var process = Process.GetCurrentProcess();\n    var fullPath = process.MainModule?.FileName?.Replace(process.MainModule.ModuleName!, string.Empty);\n    Console.WriteLine(\"Add Scan Directories: {0}\", fullPath);\n    pluginBuilder?.AddScanDirectories(fullPath!);\n\n    pluginBuilder?.IncludeFrameworks(@\"\\netstandard2.0\\*.FrameworkLib.dll\");\n\n    var runtime = Path.GetFileName(AppContext.BaseDirectory);\n    Console.WriteLine(@\"Include Plugins from: \\Plugins\\{0}\\{1}*.dll\", runtime, \"ReactiveMarbles.Plugin\");\n    pluginBuilder?.IncludePlugins(@$\"\\Plugins\\{runtime}\\{{YourPluginNamespace}}*.dll\");\n    Console.ResetColor();\n})\n```\n\n#### ReactiveMarbles.Extensions.Hosting.PluginService\n```csharp\nawait ServiceHost.Create(\n    typeof(Program),\n    args,\n    hb =\u003e hb, // Configure the HostBuilder\n    host =\u003e {}, // Configure the Host\n    nameSpace: \"ReactiveMarbles.Plugin\").ConfigureAwait(false);\n","funding_links":["https://github.com/sponsors/reactivemarbles"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivemarbles%2FExtensions.Hosting","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactivemarbles%2FExtensions.Hosting","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivemarbles%2FExtensions.Hosting/lists"}