diff --git a/CHANGELOG.md b/CHANGELOG.md index 99198b4..23f6c22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - X10D: Removed `IEnumerable.ConcatOne` - this functionality already exists with `Append`. +## [3.3.1] - 2023-08-21 + +### Fixed + +- X10D.Hosting: Fixed `AddHostedSingleton` not accepting an interface as the service type. + ## [3.3.0] - 2023-08-21 ### Added @@ -613,7 +619,8 @@ please [open an issue](https://github.com/oliverbooth/X10D/issues)! Earlier versions of this package are undocumented and unlisted from package results. -[unreleased]: https://github.com/oliverbooth/X10D/compare/v3.3.0...main +[unreleased]: https://github.com/oliverbooth/X10D/compare/v3.3.1...main +[3.3.1]: https://github.com/oliverbooth/X10D/releases/tag/v3.3.1 [3.3.0]: https://github.com/oliverbooth/X10D/releases/tag/v3.3.0 [3.2.2]: https://github.com/oliverbooth/X10D/releases/tag/v3.2.2 [3.2.0]: https://github.com/oliverbooth/X10D/releases/tag/v3.2.0 diff --git a/X10D.Hosting/src/DependencyInjection/ServiceCollectionExtensions.cs b/X10D.Hosting/src/DependencyInjection/ServiceCollectionExtensions.cs index 8df216c..ea0d3a4 100644 --- a/X10D.Hosting/src/DependencyInjection/ServiceCollectionExtensions.cs +++ b/X10D.Hosting/src/DependencyInjection/ServiceCollectionExtensions.cs @@ -29,11 +29,12 @@ public static class ServiceCollectionExtensions /// The type of the implementation to use. /// A reference to this instance after the operation has completed. public static IServiceCollection AddHostedSingleton(this IServiceCollection services) - where TService : class, IHostedService - where TImplementation : class, TService + where TService : class + where TImplementation : class, TService, IHostedService { services.AddSingleton(); - return services.AddSingleton(provider => provider.GetRequiredService()); + return services.AddSingleton(provider => + (TImplementation)provider.GetRequiredService()); } /// diff --git a/X10D.Tests/src/Hosting/ServiceCollectionTests.cs b/X10D.Tests/src/Hosting/ServiceCollectionTests.cs index 0ce3fd2..63a3db6 100644 --- a/X10D.Tests/src/Hosting/ServiceCollectionTests.cs +++ b/X10D.Tests/src/Hosting/ServiceCollectionTests.cs @@ -29,6 +29,27 @@ public class ServiceCollectionTests }); } + [Test] + public void AddHostedSingleton_ShouldRegisterServiceAsSingletonAndAsHostedService_GivenServiceAndImplTypes() + { + var services = new ServiceCollection(); + + services.AddHostedSingleton(); + + var serviceProvider = services.BuildServiceProvider(); + var service = serviceProvider.GetService(); + var hostedService = serviceProvider.GetService(); + + Assert.Multiple(() => + { + Assert.That(service, Is.Not.Null); + Assert.That(hostedService, Is.Not.Null); + Assert.IsAssignableFrom(service); + Assert.IsAssignableFrom(hostedService); + Assert.That(hostedService, Is.SameAs(service)); + }); + } + [Test] public void AddHostedSingleton_ShouldRegisterServiceTypeAsSingletonAndAsHostedService() { @@ -50,8 +71,38 @@ public class ServiceCollectionTests }); } - private sealed class TestService : IHostedService + [Test] + public void AddHostedSingleton_ShouldRegisterServiceTypeAsSingletonAndAsHostedService_GivenServiceAndImplTypes() { + var services = new ServiceCollection(); + + services.AddHostedSingleton(typeof(ITestService), typeof(TestService)); + + var serviceProvider = services.BuildServiceProvider(); + var service = serviceProvider.GetService(); + var hostedService = serviceProvider.GetService(); + + Assert.Multiple(() => + { + Assert.That(service, Is.Not.Null); + Assert.That(hostedService, Is.Not.Null); + Assert.IsAssignableFrom(service); + Assert.IsAssignableFrom(hostedService); + Assert.That(hostedService, Is.SameAs(service)); + }); + } + + private interface ITestService + { + void Foo(); + } + + private sealed class TestService : ITestService, IHostedService + { + public void Foo() + { + } + public Task StartAsync(CancellationToken cancellationToken) { return Task.CompletedTask;