diff --git a/Documents/images/platforms-windows-badge.svg b/Documents/images/platforms-windows-badge.svg new file mode 100644 index 0000000..685cc0d --- /dev/null +++ b/Documents/images/platforms-windows-badge.svg @@ -0,0 +1,28 @@ + + + platforms: linux and windows + + + + + + + + + + + + + + + platforms + + windows + + + diff --git a/Documents/images/status-mature-and-stable-badge.svg b/Documents/images/status-mature-and-stable-badge.svg new file mode 100644 index 0000000..400fce7 --- /dev/null +++ b/Documents/images/status-mature-and-stable-badge.svg @@ -0,0 +1,27 @@ + + + status: early planning phase + + + + + + + + + + + + + + + status + + mature and stable + + + + + + + diff --git a/ReadMe.md b/ReadMe.md index 7a63491..67b5989 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1,10 +1,4 @@ - - **Status:** Stable and mature. Several projects are using this library, - and it has received extensive testing on Linux and Windows. - - - **Platforms:** Cross-platform, developed on Linux but also tested and - working without any known issues on Windows. - -Nuclex.Windows.Forms.DependencyInjection +Nuclex.Windows.Forms.DependencyInjection ![Windows-only due to using Windows Forms](./Documents/images/platforms-windows-badge.svg) ![Several projects are using library and it has received extensive testting](./Documents/images/status-mature-and-stable-badge.svg) ======================================== Nuclex.Windows.Forms is a standalone, lightweight MVVM library that lets you "display" diff --git a/Source/DependencyInjectedWindowManager.cs b/Source/DependencyInjectedWindowManager.cs index 86d1a09..6cb9e59 100644 --- a/Source/DependencyInjectedWindowManager.cs +++ b/Source/DependencyInjectedWindowManager.cs @@ -1,71 +1,118 @@ -#region Apache License 2.0 -/* -Nuclex .NET Framework -Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -#endregion // Apache License 2.0 - -using System; - -#if NET6_0_OR_GREATER -using System.Runtime.Versioning; -#endif - -using Microsoft.Extensions.DependencyInjection; - -using Nuclex.Windows.Forms.AutoBinding; - -namespace Nuclex.Windows.Forms.DependencyInjection { - - /// - /// Window manager that is using Microsoft's dependency injection interfaces - /// -#if NET6_0_OR_GREATER - [SupportedOSPlatform("windows")] -#endif - public class DependencyInjectedWindowManager : WindowManager { - - /// Initializes a new window manager - /// - /// Dependency injector the window manager uses to construct view models - /// - /// - /// View model binder that will be used to bind all created views to their models - /// - public DependencyInjectedWindowManager( - IServiceProvider serviceProvider, IAutoBinder autoBinder = null - ) : - base(autoBinder) { - this.serviceProvider = serviceProvider; - } - - /// Creates an instance of the specified type - /// Type an instance will be created of - /// The created instance - /// - /// Use this to wire up your dependency injection container. By default, - /// the Activator class will be used to create instances which only works - /// if all of your view models are concrete classes. - /// - protected override object CreateInstance(Type type) { - return this.serviceProvider.GetRequiredService(type); - } - - /// The service provider used to create new instances - private readonly IServiceProvider serviceProvider; - - } - -} // namespace Nuclex.Windows.Forms.DependencyInjection +#region Apache License 2.0 +/* +Nuclex .NET Framework +Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#endregion // Apache License 2.0 + +using System; + +#if NET6_0_OR_GREATER +using System.Runtime.Versioning; +#endif + +using Microsoft.Extensions.DependencyInjection; + +using Nuclex.Windows.Forms.AutoBinding; + +namespace Nuclex.Windows.Forms.DependencyInjection { + + /// + /// Window manager that is using Microsoft's dependency injection interfaces + /// +#if NET6_0_OR_GREATER + [SupportedOSPlatform("windows")] +#endif + public class DependencyInjectedWindowManager : WindowManager { + + #region class WindowScope + + /// Manages a window-specific service scope + private class WindowScope : IWindowScope, IDisposable { + + /// Initializes a new service scope for the window + /// + /// Service provider in which to create a scope + /// + public WindowScope(IServiceProvider serviceProvider) { + this.serviceScope = serviceProvider.CreateScope(); + } + + /// Creates an instance of the specified type in the scope + /// Type an instance will be created of + /// The created instance + /// + /// Use this to wire up your dependency injection container. By default, + /// the Activator class will be used to create instances which only works + /// if all of your view models are concrete classes. + /// + public object CreateInstance(Type type) { + return this.serviceScope.ServiceProvider.GetRequiredService(type); + } + + /// Immediately destroys all services owned by the scope + public void Dispose() { + if(this.serviceScope != null) { + this.serviceScope.Dispose(); + this.serviceScope = null; + } + } + + /// Service scope that will be used to create instances + private IServiceScope serviceScope; + + } + + #endregion // class WindowScope + + /// Initializes a new window manager + /// + /// Dependency injector the window manager uses to construct view models + /// + /// + /// View model binder that will be used to bind all created views to their models + /// + public DependencyInjectedWindowManager( + IServiceProvider serviceProvider, IAutoBinder autoBinder = null + ) : + base(autoBinder) { + this.serviceProvider = serviceProvider; + } + + /// Creates an instance of the specified type + /// Type an instance will be created of + /// The created instance + /// + /// Use this to wire up your dependency injection container. By default, + /// the Activator class will be used to create instances which only works + /// if all of your view models are concrete classes. + /// + protected override object CreateInstance(Type type) { + return this.serviceProvider.GetRequiredService(type); + } + + /// Creates an instance of the specified type in a new scope + /// Type an instance will be created of + /// The created instance and the scope in which it lives + protected override IWindowScope CreateWindowScope() { + return new WindowScope(this.serviceProvider); + } + + /// The service provider used to create new instances + private readonly IServiceProvider serviceProvider; + + } + +} // namespace Nuclex.Windows.Forms.DependencyInjection diff --git a/Source/MvvmExtensions.cs b/Source/MvvmExtensions.cs index 8de87c8..514248f 100644 --- a/Source/MvvmExtensions.cs +++ b/Source/MvvmExtensions.cs @@ -22,8 +22,8 @@ using System; #if NET6_0_OR_GREATER using System.Runtime.Versioning; #endif - -using Microsoft.Extensions.DependencyInjection; + +using Microsoft.Extensions.DependencyInjection; using Nuclex.Windows.Forms.AutoBinding; using Nuclex.Windows.Forms.CommonDialogs; @@ -37,52 +37,52 @@ namespace Nuclex.Windows.Forms.DependencyInjection { #endif public static class MvvmExtensions { - /// Registers all MVVM supporting services for a WinForms application - /// Service collection the services will be registered to - /// The service collection for method chaining + /// Registers all MVVM supporting services for a WinForms application + /// Service collection the services will be registered to + /// The service collection for method chaining public static IServiceCollection AddMvvm(this IServiceCollection services) { - - // The window manager keeps track of which Window is in the foreground - // and handles opening modal or modeless windows for which it either - // binds provided view models or requests new instances. - services.AddSingleton(); - - // The IWindowManager is the main interface that should be used to - // create new windows and dialogs - services.AddSingleton( - sp => sp.GetRequiredService() - ); - - // The IActiveWindowTracker is a very simple interface to let Windows Forms - // extensions that need to display message boxes or other things query for - // the currently active top-level window. - services.AddSingleton( - sp => sp.GetRequiredService() - ); - - // The auto binder uses convention-over-configuration to automatically - // establish data bindings or call view model methods that share their name - // with button controls. - services.AddSingleton(); - - return services; - + + // The window manager keeps track of which Window is in the foreground + // and handles opening modal or modeless windows for which it either + // binds provided view models or requests new instances. + services.AddSingleton(); + + // The IWindowManager is the main interface that should be used to + // create new windows and dialogs + services.AddSingleton( + sp => sp.GetRequiredService() + ); + + // The IActiveWindowTracker is a very simple interface to let Windows Forms + // extensions that need to display message boxes or other things query for + // the currently active top-level window. + services.AddSingleton( + sp => sp.GetRequiredService() + ); + + // The auto binder uses convention-over-configuration to automatically + // establish data bindings or call view model methods that share their name + // with button controls. + services.AddSingleton(); + + return services; + } - /// Registers all MVVM supporting services for a WinForms application - /// Service collection the services will be registered to - /// The service collection for method chaining + /// Registers all MVVM supporting services for a WinForms application + /// Service collection the services will be registered to + /// The service collection for method chaining public static IServiceCollection AddCommonDialogs(this IServiceCollection services) { // Implementation of the message service that uses plain MessageBoxes // from the Win32 API to display messages to the user - services.AddSingleton(); - - // Common dialog adapter that uses the built-in common dialogs from + services.AddSingleton(); + + // Common dialog adapter that uses the built-in common dialogs from // basic WinForms to display file open, save or print dialogs - services.AddSingleton(); - - return services; + services.AddSingleton(); + + return services; }