Wrote a small helper class with extension methods to register the Nuclex.Avalonia MVVM services to a Microsoft.Extensions.DependencyInjection IoC container
This commit is contained in:
commit
708f87357e
@ -0,0 +1,31 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net462;net8.0</TargetFrameworks>
|
||||||
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
|
<AssemblyName>Nuclex.Windows.Forms.DependencyInjection</AssemblyName>
|
||||||
|
<RootNamespace>Nuclex.Windows.Forms.DependencyInjection</RootNamespace>
|
||||||
|
<IntermediateOutputPath>obj\source</IntermediateOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Tests\**" />
|
||||||
|
<EmbeddedResource Remove="Tests\**" />
|
||||||
|
<None Remove="Tests\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove=".git" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Nuclex.Avalonia\Nuclex.Avalonia (netstandard-2.0).csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
48
Properties/AssemblyInfo.cs
Normal file
48
Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#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.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("Nuclex.Avalonia.DependencyInjection")]
|
||||||
|
[assembly: AssemblyProduct("Nuclex.Avalonia.DependencyInjection")]
|
||||||
|
[assembly: AssemblyDescription("Add-on module to use Nuclex.Avalonia MVVM with Microsoft dependency injection interfaces")]
|
||||||
|
[assembly: AssemblyCompany("Nuclex Development Labs")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © Markus Ewald / Nuclex Development Labs 2002-2025")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("4b185e46-672f-4629-98e8-82db07aa8147")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("1.3.0")]
|
116
Source/DependencyInjectedWindowManager.cs
Normal file
116
Source/DependencyInjectedWindowManager.cs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#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.Avalonia.AutoBinding;
|
||||||
|
|
||||||
|
namespace Nuclex.Avalonia.DependencyInjection {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Window manager that is using Microsoft's dependency injection interfaces
|
||||||
|
/// </summary>
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
#endif
|
||||||
|
public class DependencyInjectedWindowManager : WindowManager {
|
||||||
|
|
||||||
|
#region class WindowScope
|
||||||
|
|
||||||
|
/// <summary>Manages a window-specific service scope</summary>
|
||||||
|
private class WindowScope : IWindowScope, IDisposable {
|
||||||
|
|
||||||
|
/// <summary>Initializes a new service scope for the window</summary>
|
||||||
|
/// <param name="serviceProvider">
|
||||||
|
/// Service provider in which to create a scope
|
||||||
|
/// </param>
|
||||||
|
public WindowScope(IServiceProvider serviceProvider) {
|
||||||
|
this.serviceScope = serviceProvider.CreateScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates an instance of the specified type in the scope</summary>
|
||||||
|
/// <param name="type">Type an instance will be created of</param>
|
||||||
|
/// <returns>The created instance</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 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.
|
||||||
|
/// </remarks>
|
||||||
|
public object CreateInstance(Type type) {
|
||||||
|
return this.serviceScope.ServiceProvider.GetRequiredService(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Immediately destroys all services owned by the scope</summary>
|
||||||
|
public void Dispose() {
|
||||||
|
if(this.serviceScope != null) {
|
||||||
|
this.serviceScope.Dispose();
|
||||||
|
this.serviceScope = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Service scope that will be used to create instances</summary>
|
||||||
|
private IServiceScope serviceScope;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // class WindowScope
|
||||||
|
|
||||||
|
/// <summary>Initializes a new window manager</summary>
|
||||||
|
/// <param name="serviceProvider">
|
||||||
|
/// Dependency injector the window manager uses to construct view models
|
||||||
|
/// </param>
|
||||||
|
/// <param name="autoBinder">
|
||||||
|
/// View model binder that will be used to bind all created views to their models
|
||||||
|
/// </param>
|
||||||
|
public DependencyInjectedWindowManager(
|
||||||
|
IServiceProvider serviceProvider, IAutoBinder autoBinder = null
|
||||||
|
) :
|
||||||
|
base(autoBinder) {
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates an instance of the specified type</summary>
|
||||||
|
/// <param name="type">Type an instance will be created of</param>
|
||||||
|
/// <returns>The created instance</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// 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.
|
||||||
|
/// </remarks>
|
||||||
|
protected override object CreateInstance(Type type) {
|
||||||
|
return this.serviceProvider.GetRequiredService(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates a new scope in which window-specific services will live</summary>
|
||||||
|
/// <returns>The new scope managing the lifetime of window-specific services</returns>
|
||||||
|
protected override IWindowScope CreateWindowScope() {
|
||||||
|
return new WindowScope(this.serviceProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>The service provider used to create new instances</summary>
|
||||||
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Nuclex.Avalonia.DependencyInjection
|
83
Source/MvvmExtensions.cs
Normal file
83
Source/MvvmExtensions.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#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;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
using Nuclex.Avalonia.AutoBinding;
|
||||||
|
using Nuclex.Avalonia.Messages;
|
||||||
|
|
||||||
|
namespace Nuclex.Avalonia.DependencyInjection {
|
||||||
|
|
||||||
|
/// <summary>Sets up the service bindings for an MVVM-based application</summary>
|
||||||
|
public static class MvvmExtensions {
|
||||||
|
|
||||||
|
/// <summary>Registers all MVVM supporting services for a WinForms application</summary>
|
||||||
|
/// <param name="services">Service collection the services will be registered to</param>
|
||||||
|
/// <returns>The service collection for method chaining</returns>
|
||||||
|
public static IServiceCollection AddMvvm(this IServiceCollection services) {
|
||||||
|
|
||||||
|
// Allow displaying message boxes via the AvaloniaMessagePresenter which wraps
|
||||||
|
// the MessageBox.Avalonia library
|
||||||
|
services.AddSingleton<IMessageService, AvaloniaMessagePresenter>();
|
||||||
|
|
||||||
|
// 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<WindowManager, DependencyInjectedWindowManager>();
|
||||||
|
|
||||||
|
// The IWindowManager is the main interface that should be used to
|
||||||
|
// create new windows and dialogs
|
||||||
|
services.AddSingleton<IWindowManager>(
|
||||||
|
sp => sp.GetRequiredService<WindowManager>()
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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<IActiveWindowTracker>(
|
||||||
|
sp => sp.GetRequiredService<WindowManager>()
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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<IAutoBinder, ConventionBinder>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Registers all MVVM supporting services for a WinForms application</summary>
|
||||||
|
/// <param name="services">Service collection the services will be registered to</param>
|
||||||
|
/// <returns>The service collection for method chaining</returns>
|
||||||
|
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<IMessageService, AvaloniaMessagePresenter>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Nuclex.Avalonia.DependencyInjection
|
Loading…
Reference in New Issue
Block a user