diff --git a/Extensions.Hosting.WinForms.sln b/Extensions.Hosting.WinForms.sln index 05fd95a..65cf382 100644 --- a/Extensions.Hosting.WinForms.sln +++ b/Extensions.Hosting.WinForms.sln @@ -23,24 +23,25 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{63A3C280-DDDF-4BC1-9B8F-AC8D9F949B3E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetEvolve.Extensions.Hosting.WinForms", "src\NetEvolve.Extensions.Hosting.WinForms\NetEvolve.Extensions.Hosting.WinForms.csproj", "{5501B170-5917-4568-9EAC-8853D14238A1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetEvolve.Extensions.Hosting.WinForms", "src\NetEvolve.Extensions.Hosting.WinForms\NetEvolve.Extensions.Hosting.WinForms.csproj", "{5501B170-5917-4568-9EAC-8853D14238A1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{8A14AF25-8CF0-494E-9D50-2FAE3CC9A50A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetEvolve.Extensions.Hosting.WinForms.Tests.Unit", "tests\NetEvolve.Extensions.Hosting.WinForms.Tests.Unit\NetEvolve.Extensions.Hosting.WinForms.Tests.Unit.csproj", "{F7BA85AD-CBD1-4F99-BC28-42DF1253BAE8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetEvolve.Extensions.Hosting.WinForms.Tests.Unit", "tests\NetEvolve.Extensions.Hosting.WinForms.Tests.Unit\NetEvolve.Extensions.Hosting.WinForms.Tests.Unit.csproj", "{F7BA85AD-CBD1-4F99-BC28-42DF1253BAE8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetEvolve.Extensions.Hosting.WinForms.Tests.Integration", "tests\NetEvolve.Extensions.Hosting.WinForms.Tests.Integration\NetEvolve.Extensions.Hosting.WinForms.Tests.Integration.csproj", "{22F991BF-06C3-4B35-BCA2-DD61959C187F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetEvolve.Extensions.Hosting.WinForms.Tests.Integration", "tests\NetEvolve.Extensions.Hosting.WinForms.Tests.Integration\NetEvolve.Extensions.Hosting.WinForms.Tests.Integration.csproj", "{22F991BF-06C3-4B35-BCA2-DD61959C187F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetEvolve.Extensions.Hosting.WinForms.Tests.Architecture", "tests\NetEvolve.Extensions.Hosting.WinForms.Tests.Architecture\NetEvolve.Extensions.Hosting.WinForms.Tests.Architecture.csproj", "{DF47FD5F-2F7F-470B-98A2-9C5266AA0FBD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetEvolve.Extensions.Hosting.WinForms.Tests.Architecture", "tests\NetEvolve.Extensions.Hosting.WinForms.Tests.Architecture\NetEvolve.Extensions.Hosting.WinForms.Tests.Architecture.csproj", "{DF47FD5F-2F7F-470B-98A2-9C5266AA0FBD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "xample", "xample", "{B241FEA0-8C20-49E2-BD16-36ACBD4A00C9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xample.Simple", "xample\Xample.Simple\Xample.Simple.csproj", "{F8CFBE08-1E6F-4CC6-BF56-CE2E72B19A16}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {5501B170-5917-4568-9EAC-8853D14238A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5501B170-5917-4568-9EAC-8853D14238A1}.Debug|Any CPU.Build.0 = Debug|Any CPU @@ -58,11 +59,22 @@ Global {DF47FD5F-2F7F-470B-98A2-9C5266AA0FBD}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF47FD5F-2F7F-470B-98A2-9C5266AA0FBD}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF47FD5F-2F7F-470B-98A2-9C5266AA0FBD}.Release|Any CPU.Build.0 = Release|Any CPU + {F8CFBE08-1E6F-4CC6-BF56-CE2E72B19A16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8CFBE08-1E6F-4CC6-BF56-CE2E72B19A16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8CFBE08-1E6F-4CC6-BF56-CE2E72B19A16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8CFBE08-1E6F-4CC6-BF56-CE2E72B19A16}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {5501B170-5917-4568-9EAC-8853D14238A1} = {63A3C280-DDDF-4BC1-9B8F-AC8D9F949B3E} {F7BA85AD-CBD1-4F99-BC28-42DF1253BAE8} = {8A14AF25-8CF0-494E-9D50-2FAE3CC9A50A} {22F991BF-06C3-4B35-BCA2-DD61959C187F} = {8A14AF25-8CF0-494E-9D50-2FAE3CC9A50A} {DF47FD5F-2F7F-470B-98A2-9C5266AA0FBD} = {8A14AF25-8CF0-494E-9D50-2FAE3CC9A50A} + {F8CFBE08-1E6F-4CC6-BF56-CE2E72B19A16} = {B241FEA0-8C20-49E2-BD16-36ACBD4A00C9} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {89AAE175-2ADC-48FB-8667-A87EA55FD851} EndGlobalSection EndGlobal diff --git a/src/NetEvolve.Extensions.Hosting.WinForms/Internals/WindowsFormsSynchronizationContextProvider.cs b/src/NetEvolve.Extensions.Hosting.WinForms/Internals/WindowsFormsSynchronizationContextProvider.cs index 4b940e3..1aa8b6f 100644 --- a/src/NetEvolve.Extensions.Hosting.WinForms/Internals/WindowsFormsSynchronizationContextProvider.cs +++ b/src/NetEvolve.Extensions.Hosting.WinForms/Internals/WindowsFormsSynchronizationContextProvider.cs @@ -8,11 +8,8 @@ /// internal sealed class WindowsFormsSynchronizationContextProvider - : IWindowsFormsSynchronizationContextProvider, - IDisposable + : IWindowsFormsSynchronizationContextProvider { - private bool _disposedValue; - internal WindowsFormsSynchronizationContext Context { get; set; } = default!; /// @@ -145,24 +142,4 @@ public async ValueTask InvokeAsync( ); return await tcs.Task.WaitAsync(cancellationToken).ConfigureAwait(true); } - - private void Dispose(bool disposing) - { - if (!_disposedValue) - { - if (disposing) - { - Context.Dispose(); - } - - _disposedValue = true; - } - } - - public void Dispose() - { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose(true); - GC.SuppressFinalize(this); - } } diff --git a/src/NetEvolve.Extensions.Hosting.WinForms/README.md b/src/NetEvolve.Extensions.Hosting.WinForms/README.md index 570f4e7..d748be2 100644 --- a/src/NetEvolve.Extensions.Hosting.WinForms/README.md +++ b/src/NetEvolve.Extensions.Hosting.WinForms/README.md @@ -1 +1,58 @@ -Please give the customer a brief introduction about this library, and how to use it. +# NetEvolve.Extensions.Hosting.WinForms + +[![Nuget](https://img.shields.io/nuget/v/NetEvolve.Extensions.Hosting.WinForms?logo=nuget)](https://www.nuget.org/packages/NetEvolve.Extensions.Hosting.WinForms/) +[![Nuget](https://img.shields.io/nuget/dt/NetEvolve.Extensions.Hosting.WinForms?logo=nuget)](https://www.nuget.org/packages/NetEvolve.Extensions.Hosting.WinForms/) + +The main purpose of this package is to provide a way to use the `Microsoft.Extensions.Hosting` for WinForms applications, allowing the use of dependency injection, configuration, logging, and other features provided by the `Microsoft.Extensions` libraries. + +:bulb: This package is available for .NET 6.0 and later. + +## Installation +To use this package, you need to add the package to your project. You can do this by using the NuGet package manager or by using the dotnet CLI. +```powershell +dotnet add package NetEvolve.Extensions.Hosting.WinForms +``` + +## Usage +To use the `Microsoft.Extensions.Hosting` in a WinForms application, you just need to create a new `HostBuilder` and configure it as you would do in a console application. + +```csharp +namespace WinForms; + +using Microsoft.Extensions.Hosting; +using NetEvolve.Extensions.Hosting.WinForms; + +internal static class Program +{ + internal static async Task Main() => + await CreateHostBuilder().Build().RunAsync().ConfigureAwait(false); + + public static IHostBuilder CreateHostBuilder() => + Host.CreateDefaultBuilder().UseWindowsForms(); +} +``` + +Therefore, you can use the `Microsoft.Extensions.DependencyInjection` to register services and inject them into your forms. + +```csharp +namespace WinForms; + +using Microsoft.Extensions.DependencyInjection; +using System.Windows.Forms; + +public partial class Form1 : Form +{ + private readonly ILogger _logger; + + public Form1(ILogger logger) + { + _logger = logger; + InitializeComponent(); + } + + private void Form1_Load(object sender, EventArgs e) + { + _logger.LogInformation("Form loaded."); + } +} +``` \ No newline at end of file diff --git a/xample/Xample.Simple/Form1.Designer.cs b/xample/Xample.Simple/Form1.Designer.cs new file mode 100644 index 0000000..5008edd --- /dev/null +++ b/xample/Xample.Simple/Form1.Designer.cs @@ -0,0 +1,45 @@ +namespace Xample.Simple +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + SuspendLayout(); + // + // Form1 + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Name = "Form1"; + Text = "Form1"; + ResumeLayout(false); + } + + #endregion + } +} diff --git a/xample/Xample.Simple/Form1.cs b/xample/Xample.Simple/Form1.cs new file mode 100644 index 0000000..5251efe --- /dev/null +++ b/xample/Xample.Simple/Form1.cs @@ -0,0 +1,19 @@ +namespace Xample.Simple; + +using Microsoft.Extensions.Logging; + +internal partial class Form1 : Form +{ + private readonly ILogger _logger; + + public Form1(ILogger logger) + { + _logger = logger; + InitializeComponent(); + + Form1Created(); + } + + [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "From1 created.")] + public partial void Form1Created(); +} diff --git a/xample/Xample.Simple/Form1.resx b/xample/Xample.Simple/Form1.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/xample/Xample.Simple/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/xample/Xample.Simple/Program.cs b/xample/Xample.Simple/Program.cs new file mode 100644 index 0000000..e75d079 --- /dev/null +++ b/xample/Xample.Simple/Program.cs @@ -0,0 +1,13 @@ +namespace Xample.Simple; + +using Microsoft.Extensions.Hosting; +using NetEvolve.Extensions.Hosting.WinForms; + +internal static class Program +{ + internal static async Task Main() => + await CreateHostBuilder().Build().RunAsync().ConfigureAwait(false); + + public static IHostBuilder CreateHostBuilder() => + Host.CreateDefaultBuilder().UseWindowsForms(); +} diff --git a/xample/Xample.Simple/Xample.Simple.csproj b/xample/Xample.Simple/Xample.Simple.csproj new file mode 100644 index 0000000..1787340 --- /dev/null +++ b/xample/Xample.Simple/Xample.Simple.csproj @@ -0,0 +1,15 @@ + + + + WinExe + net6.0-windows + enable + true + enable + + + + + + + \ No newline at end of file