From a7c2796cbe170c193f4e2e3f7293dbe97b0203cc Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 18 Mar 2024 18:56:20 -0500 Subject: [PATCH 01/10] refactor: Rename variable to implementationType --- src/Core/TypeFinder.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Core/TypeFinder.cs b/src/Core/TypeFinder.cs index e6864fd..af704e1 100644 --- a/src/Core/TypeFinder.cs +++ b/src/Core/TypeFinder.cs @@ -55,9 +55,9 @@ private static IEnumerable GetSubtypesOf(IEnumerable(); foreach (PluginAttribute pluginAttribute in pluginAttributes) { - Type type = pluginAttribute.PluginType; - if (typeof(TSupertype).IsAssignableFrom(type)) - yield return (TSupertype)Activator.CreateInstance(type); + Type implementationType = pluginAttribute.PluginType; + if (typeof(TSupertype).IsAssignableFrom(implementationType)) + yield return (TSupertype)Activator.CreateInstance(implementationType); } } } From c6fe613d0dca1050f64b11ea47ea97169ab91e7e Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 18 Mar 2024 18:58:46 -0500 Subject: [PATCH 02/10] chore: Add package reference --- src/Core/CPlugin.Net.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/CPlugin.Net.csproj b/src/Core/CPlugin.Net.csproj index 57df5ec..7fd8f7c 100644 --- a/src/Core/CPlugin.Net.csproj +++ b/src/Core/CPlugin.Net.csproj @@ -26,6 +26,7 @@ + From cfe305d0bab9fd71b64a538daf35a488e3f3ad5e Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Mon, 18 Mar 2024 19:18:07 -0500 Subject: [PATCH 03/10] cleanup: Remove comment of exception --- src/Core/TypeFinder.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Core/TypeFinder.cs b/src/Core/TypeFinder.cs index af704e1..2e740eb 100644 --- a/src/Core/TypeFinder.cs +++ b/src/Core/TypeFinder.cs @@ -28,9 +28,6 @@ public static class TypeFinder /// or if no assembly uses . /// This method never returns null. /// - /// - /// assemblies is null. - /// public static IEnumerable FindSubtypesOf() where TSupertype : class => FindSubtypesOf(PluginLoader.Assemblies); From 00c8a9663292abb9e7fd842f0725373dfd6ec04f Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 19 Mar 2024 12:32:01 -0500 Subject: [PATCH 04/10] feat: Add support for dependency injection via constructor --- src/Core/ServiceCollectionExtensions.cs | 76 +++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/Core/ServiceCollectionExtensions.cs diff --git a/src/Core/ServiceCollectionExtensions.cs b/src/Core/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..0b763a9 --- /dev/null +++ b/src/Core/ServiceCollectionExtensions.cs @@ -0,0 +1,76 @@ +using Microsoft.Extensions.DependencyInjection; +using System.Reflection; + +namespace CPlugin.Net; + +/// +/// Extension methods for adding services to an . +/// +public static class CPluginServiceCollectionExtensions +{ + /// + /// Adds the subtypes that implement the contract specified by + /// to the service collection, using the assemblies loaded by . + /// + /// + /// The type of contract (base type) shared between the host application and the plugins. + /// + /// + /// The to add the service to. + /// + /// + /// Specifies the lifetime of the services to be added to the service collection. + /// + /// + /// This method uses the type to add the implementations of the contract + /// to the service collection, so plugins must use it. + /// + /// + /// A reference to this instance after the operation has completed. + /// + public static IServiceCollection AddSubtypesOf( + this IServiceCollection services, + ServiceLifetime serviceLifetime) where TSupertype : class + => services.AddSubtypesOf(PluginLoader.Assemblies, serviceLifetime); + + // This method is only to be used for testing. + // This way you don't have to depend on the plugin loader when testing. + internal static IServiceCollection AddSubtypesOf( + this IServiceCollection services, + IEnumerable assemblies, + ServiceLifetime serviceLifetime) where TSupertype : class + { + if (assemblies is null) + throw new ArgumentNullException(nameof(assemblies)); + + foreach (Assembly assembly in assemblies) + { + var pluginAttributes = assembly.GetCustomAttributes(); + foreach (PluginAttribute pluginAttribute in pluginAttributes) + { + Type implementationType = pluginAttribute.PluginType; + if (typeof(TSupertype).IsAssignableFrom(implementationType)) + { + services.AddService( + serviceType: typeof(TSupertype), + implementationType, + serviceLifetime); + } + } + } + + return services; + } + + private static IServiceCollection AddService( + this IServiceCollection services, + Type serviceType, + Type implementationType, + ServiceLifetime serviceLifetime) => serviceLifetime switch + { + ServiceLifetime.Singleton => services.AddSingleton(serviceType, implementationType), + ServiceLifetime.Transient => services.AddTransient(serviceType, implementationType), + ServiceLifetime.Scoped => services.AddScoped(serviceType, implementationType), + _ => throw new NotSupportedException($"Lifetime '{serviceLifetime}' is not supported.") + }; +} From e76cb3bcc79dd46e0b0900275753836e871b988d Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 19 Mar 2024 15:39:32 -0500 Subject: [PATCH 05/10] test: Add unit tests for the CPluginServiceCollectionExtensions type --- ...CPluginServiceCollectionExtensionsTests.cs | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs diff --git a/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs b/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs new file mode 100644 index 0000000..993c744 --- /dev/null +++ b/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs @@ -0,0 +1,170 @@ +[assembly: Plugin(typeof(ServiceTest1))] +[assembly: Plugin(typeof(ServiceTest2))] +[assembly: Plugin(typeof(ServiceTestExample))] + +namespace CPlugin.Net.Tests.Core; + +public class ServiceTestBase { } +public class ServiceTestExample : ServiceTestBase { } +public abstract class ServiceTestAbstract { } +public interface IServiceTest +{ + int Execute(); +} + +public class ServiceTest1 : IServiceTest +{ + public int Execute() => 1; +} +public class ServiceTest2 : IServiceTest +{ + public int Execute() => 1; +} + +public class CPluginServiceCollectionExtensionsTests +{ + [TestCase(ServiceLifetime.Singleton)] + [TestCase(ServiceLifetime.Transient)] + [TestCase(ServiceLifetime.Scoped)] + public void AddSubtypesOf_WhenSubtypesArePresent_ShouldAddsSubtypesToServiceCollection( + ServiceLifetime serviceLifetime) + { + // Arrange + var services = new ServiceCollection(); + var assemblies = new[] + { + typeof(CPluginServiceCollectionExtensionsTests).Assembly + }; + int[] expectedValues = { 1, 1 }; + + // Act + services.AddSubtypesOf(assemblies, serviceLifetime); + var testingServices = services + .BuildServiceProvider() + .GetServices(); + + int[] values = testingServices + .Select(service => service.Execute()) + .ToArray(); + + // Assert + values.Should().BeEquivalentTo(expectedValues); + } + + [Test] + public void AddSubtypesOf_WhenLifetimeIsInvalid_ShouldThrowNotSupportedException() + { + // Arrange + var services = new ServiceCollection(); + var assemblies = new[] + { + typeof(CPluginServiceCollectionExtensionsTests).Assembly + }; + var serviceLifetime = (ServiceLifetime)500; + + // Act + Action act = () => services.AddSubtypesOf(assemblies, serviceLifetime); + + // Assert + act.Should().Throw(); + } + + [Test] + public void AddSubtypesOf_WhenSupertypeDoesNotHaveSubtypes_ShouldNotAddServicesToContainer() + { + // Arrange + var services = new ServiceCollection(); + var assemblies = new[] + { + typeof(CPluginServiceCollectionExtensionsTests).Assembly + }; + var serviceLifetime = ServiceLifetime.Transient; + + // Act + services.AddSubtypesOf(assemblies, serviceLifetime); + var testingServices = services + .BuildServiceProvider() + .GetServices(); + + // Assert + testingServices.Should().BeEmpty(); + } + + [Test] + public void AddSubtypesOf_WhenThereAreNoAssembliesLoaded_ShouldNotAddServicesToContainer() + { + // Arrange + var services = new ServiceCollection(); + var assemblies = Enumerable.Empty(); + var serviceLifetime = ServiceLifetime.Transient; + + // Act + services.AddSubtypesOf(assemblies, serviceLifetime); + var testingServices = services + .BuildServiceProvider() + .GetServices(); + + // Assert + testingServices.Should().BeEmpty(); + } + + [Test] + public void AddSubtypesOf_WhenNoAssemblyUsesPluginAttribute_ShouldNotAddServicesToContainer() + { + // Arrange + var services = new ServiceCollection(); + var assemblies = new[] + { + typeof(TestProject.PluginHost.Employee).Assembly, + typeof(TestProject.Contracts.ICommand).Assembly + }; + var serviceLifetime = ServiceLifetime.Transient; + + // Act + services.AddSubtypesOf(assemblies, serviceLifetime); + var testingServices = services + .BuildServiceProvider() + .GetServices(); + + // Assert + testingServices.Should().BeEmpty(); + } + + [Test] + public void AddSubtypesOf_WhenSupertypeIsNotInterfaceOrAbstractClass_ShouldNotThrowException() + { + // Arrange + var services = new ServiceCollection(); + var assemblies = new[] + { + typeof(TypeFinderTests).Assembly + }; + var serviceLifetime = ServiceLifetime.Transient; + + // Act + services.AddSubtypesOf(assemblies, serviceLifetime); + var testingServices = services + .BuildServiceProvider() + .GetServices(); + + // Assert + testingServices.Should().HaveCount(1); + } + + [Test] + public void AddSubtypesOf_WhenArgumentIsNull_ShouldThrowArgumentNullException() + { + // Arrange + var services = new ServiceCollection(); + IEnumerable assemblies = default; + var serviceLifetime = ServiceLifetime.Transient; + + // Act + Action act = () => services.AddSubtypesOf(assemblies, serviceLifetime); + + // Assert + act.Should() + .Throw() + .WithParameterName(nameof(assemblies)); + } +} From 1d0a085ae114aaa3f98e3412b65c098aee1eb69d Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 19 Mar 2024 19:17:37 -0500 Subject: [PATCH 06/10] docs: Add sample project about dependency injection via constructor --- CPlugin.Net.sln | 14 +++++++---- samples/Contracts/ITestService.cs | 6 +++++ .../WebApi/Controllers/ServiceController.cs | 10 ++++++++ samples/HostApplications/WebApi/Program.cs | 2 ++ .../HostApplications/WebApi/appsettings.json | 4 +++- .../Example.DependencyInjectionPlugin.csproj | 9 ++++++++ .../DependencyInjectionPlugin/GlobalUsings.cs | 3 +++ .../DependencyInjectionPlugin/TestService.cs | 23 +++++++++++++++++++ samples/Test/WebApi/Get.cs | 19 +++++++++++++++ 9 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 samples/Contracts/ITestService.cs create mode 100644 samples/HostApplications/WebApi/Controllers/ServiceController.cs create mode 100644 samples/Plugins/DependencyInjectionPlugin/Example.DependencyInjectionPlugin.csproj create mode 100644 samples/Plugins/DependencyInjectionPlugin/GlobalUsings.cs create mode 100644 samples/Plugins/DependencyInjectionPlugin/TestService.cs diff --git a/CPlugin.Net.sln b/CPlugin.Net.sln index c4aa9cb..4d4877e 100644 --- a/CPlugin.Net.sln +++ b/CPlugin.Net.sln @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.HostWebApi", "sampl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.SharedEntities", "samples\SharedEntities\Example.SharedEntities.csproj", "{F66A1430-3F32-4E25-8966-54D502D216DE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.DependencyInjectionPlugin", "samples\Plugins\DependencyInjectionPlugin\Example.DependencyInjectionPlugin.csproj", "{28065D77-B890-47DE-B695-04E388176925}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.JsonPlugin", "samples\Plugins\JsonPlugin\Example.JsonPlugin.csproj", "{C5B8EF73-7DB5-441F-AE38-0988751A896B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example.OldJsonPlugin", "samples\Plugins\OldJsonPlugin\Example.OldJsonPlugin.csproj", "{1ADE3B86-00EF-4976-8B67-09B360B149FA}" @@ -98,6 +100,10 @@ Global {18534944-583B-4924-AC5B-E0655FD92AAC}.Debug|Any CPU.Build.0 = Debug|Any CPU {18534944-583B-4924-AC5B-E0655FD92AAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {18534944-583B-4924-AC5B-E0655FD92AAC}.Release|Any CPU.Build.0 = Release|Any CPU + {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Release|Any CPU.Build.0 = Release|Any CPU {0F27C776-F284-4C94-86C9-0FF089245E13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0F27C776-F284-4C94-86C9-0FF089245E13}.Debug|Any CPU.Build.0 = Debug|Any CPU {0F27C776-F284-4C94-86C9-0FF089245E13}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -122,10 +128,10 @@ Global {0BCD3305-F0D5-43E6-B879-EEF0827558A8}.Debug|Any CPU.Build.0 = Debug|Any CPU {0BCD3305-F0D5-43E6-B879-EEF0827558A8}.Release|Any CPU.ActiveCfg = Release|Any CPU {0BCD3305-F0D5-43E6-B879-EEF0827558A8}.Release|Any CPU.Build.0 = Release|Any CPU - {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E64908D-DC48-4B83-BB25-CF36821EB37F}.Release|Any CPU.Build.0 = Release|Any CPU + {28065D77-B890-47DE-B695-04E388176925}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28065D77-B890-47DE-B695-04E388176925}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28065D77-B890-47DE-B695-04E388176925}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28065D77-B890-47DE-B695-04E388176925}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/samples/Contracts/ITestService.cs b/samples/Contracts/ITestService.cs new file mode 100644 index 0000000..c444cf0 --- /dev/null +++ b/samples/Contracts/ITestService.cs @@ -0,0 +1,6 @@ +namespace Example.Contracts; + +public interface ITestService +{ + string Execute(); +} diff --git a/samples/HostApplications/WebApi/Controllers/ServiceController.cs b/samples/HostApplications/WebApi/Controllers/ServiceController.cs new file mode 100644 index 0000000..3566475 --- /dev/null +++ b/samples/HostApplications/WebApi/Controllers/ServiceController.cs @@ -0,0 +1,10 @@ +namespace Example.HostWebApi.Controllers; + +[ApiController] +[Route("[controller]")] +public class ServiceController +{ + [HttpGet] + public ActionResult Get(ITestService service) + => service.Execute(); +} diff --git a/samples/HostApplications/WebApi/Program.cs b/samples/HostApplications/WebApi/Program.cs index 3bbb2a2..18e28da 100644 --- a/samples/HostApplications/WebApi/Program.cs +++ b/samples/HostApplications/WebApi/Program.cs @@ -18,6 +18,8 @@ mvcBuilder.PartManager.ApplicationParts.Add(new AssemblyPart(assembly)); } +builder.Services.AddSubtypesOf(ServiceLifetime.Transient); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(options => diff --git a/samples/HostApplications/WebApi/appsettings.json b/samples/HostApplications/WebApi/appsettings.json index a9d4f70..45de423 100644 --- a/samples/HostApplications/WebApi/appsettings.json +++ b/samples/HostApplications/WebApi/appsettings.json @@ -6,8 +6,10 @@ } }, "AllowedHosts": "*", + "ServiceName": "TestService", "Plugins": [ "Example.AppointmentPlugin.dll", - "Example.PersonPlugin.dll" + "Example.PersonPlugin.dll", + "Example.DependencyInjectionPlugin.dll" ] } diff --git a/samples/Plugins/DependencyInjectionPlugin/Example.DependencyInjectionPlugin.csproj b/samples/Plugins/DependencyInjectionPlugin/Example.DependencyInjectionPlugin.csproj new file mode 100644 index 0000000..0f84721 --- /dev/null +++ b/samples/Plugins/DependencyInjectionPlugin/Example.DependencyInjectionPlugin.csproj @@ -0,0 +1,9 @@ + + + + $(WebApiProjectDir) + Library + true + + + diff --git a/samples/Plugins/DependencyInjectionPlugin/GlobalUsings.cs b/samples/Plugins/DependencyInjectionPlugin/GlobalUsings.cs new file mode 100644 index 0000000..d51cdec --- /dev/null +++ b/samples/Plugins/DependencyInjectionPlugin/GlobalUsings.cs @@ -0,0 +1,3 @@ +global using Example.Contracts; +global using CPlugin.Net; +global using Example.DependencyInjectionPlugin; diff --git a/samples/Plugins/DependencyInjectionPlugin/TestService.cs b/samples/Plugins/DependencyInjectionPlugin/TestService.cs new file mode 100644 index 0000000..4074d4e --- /dev/null +++ b/samples/Plugins/DependencyInjectionPlugin/TestService.cs @@ -0,0 +1,23 @@ +[assembly: Plugin(typeof(TestService))] + +namespace Example.DependencyInjectionPlugin; + +public class TestService : ITestService +{ + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + + public TestService( + ILogger logger, + IConfiguration configuration) + { + _logger = logger; + _configuration = configuration; + } + + public string Execute() + { + _logger.LogInformation("TestService"); + return _configuration["ServiceName"]; + } +} diff --git a/samples/Test/WebApi/Get.cs b/samples/Test/WebApi/Get.cs index 98a062f..7509337 100644 --- a/samples/Test/WebApi/Get.cs +++ b/samples/Test/WebApi/Get.cs @@ -102,4 +102,23 @@ public async Task Get_WhenWeatherForecastAreObtained_ShouldReturnsHttpStatusCode result.IsSuccess.Should().BeTrue(); result.Data.Should().HaveCount(expectedWeatherForecast); } + + [Test] + public async Task Get_WhenServiceNameIsObtained_ShouldReturnsHttpStatusCodeOk() + { + // Arrange + using var factory = new WebApplicationFactory(); + var client = factory.CreateClient(); + var expectedServiceName = "TestService"; + + // Act + var httpResponse = await client.GetAsync("/Service"); + var result = await httpResponse + .Content + .ReadAsStringAsync(); + + // Asserts + httpResponse.StatusCode.Should().Be(HttpStatusCode.OK); + result.Should().Be(expectedServiceName); + } } From e86bb267c4f1025541576e30ad0a58ecf9ec0707 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 19 Mar 2024 19:23:39 -0500 Subject: [PATCH 07/10] chore: Update dotnetcore.yml --- .github/workflows/dotnetcore.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index c099da5..8eb284a 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -30,4 +30,5 @@ jobs: dotnet build ./samples/Plugins/PersonPlugin/Example.PersonPlugin.csproj -c Release dotnet build ./samples/Plugins/JsonPlugin/Example.JsonPlugin.csproj -c Release dotnet build ./samples/Plugins/OldJsonPlugin/Example.OldJsonPlugin.csproj -c Release + dotnet build ./samples/Plugins/DependencyInjectionPlugin/Example.DependencyInjectionPlugin.csproj -c Release dotnet test ./samples/Test/Example.Test.csproj -c Release \ No newline at end of file From d6afa0737b94a4e8e3da32b9fce7af8cd0a4598f Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 19 Mar 2024 21:09:37 -0500 Subject: [PATCH 08/10] refactor: Rename test names --- .../CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs | 2 +- tests/CPlugin.Net/Core/TypeFinderTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs b/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs index 993c744..8be8dde 100644 --- a/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs +++ b/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs @@ -26,7 +26,7 @@ public class CPluginServiceCollectionExtensionsTests [TestCase(ServiceLifetime.Singleton)] [TestCase(ServiceLifetime.Transient)] [TestCase(ServiceLifetime.Scoped)] - public void AddSubtypesOf_WhenSubtypesArePresent_ShouldAddsSubtypesToServiceCollection( + public void AddSubtypesOf_WhenSupertypeHasSubtypes_ShouldAddsSubtypesToServiceCollection( ServiceLifetime serviceLifetime) { // Arrange diff --git a/tests/CPlugin.Net/Core/TypeFinderTests.cs b/tests/CPlugin.Net/Core/TypeFinderTests.cs index 6881ae6..2705b77 100644 --- a/tests/CPlugin.Net/Core/TypeFinderTests.cs +++ b/tests/CPlugin.Net/Core/TypeFinderTests.cs @@ -24,7 +24,7 @@ public class Runner2 : IRunner public class TypeFinderTests { [Test] - public void FindSubtypesOf_WhenSubtypesArePresent_ShouldReturnsInstancesOfSubtypes() + public void FindSubtypesOf_WhenSupertypeHasSubtypes_ShouldReturnsInstancesOfSubtypes() { // Arrange var assemblies = new[] From a5962402c8b018c22b0289297c5e43c06f341701 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 19 Mar 2024 21:11:19 -0500 Subject: [PATCH 09/10] refactor: inject an enumerable to get the first element --- .../HostApplications/WebApi/Controllers/ServiceController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/HostApplications/WebApi/Controllers/ServiceController.cs b/samples/HostApplications/WebApi/Controllers/ServiceController.cs index 3566475..9b0c84d 100644 --- a/samples/HostApplications/WebApi/Controllers/ServiceController.cs +++ b/samples/HostApplications/WebApi/Controllers/ServiceController.cs @@ -5,6 +5,6 @@ public class ServiceController { [HttpGet] - public ActionResult Get(ITestService service) - => service.Execute(); + public ActionResult Get(IEnumerable services) + => services.First().Execute(); } From b7e9179fa26c3198bd36adb3f5cd553839a7d939 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Wed, 20 Mar 2024 08:50:22 -0500 Subject: [PATCH 10/10] refactor: Change type in the typeof operator --- .../CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs b/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs index 8be8dde..9992ab0 100644 --- a/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs +++ b/tests/CPlugin.Net/Core/CPluginServiceCollectionExtensionsTests.cs @@ -137,7 +137,7 @@ public void AddSubtypesOf_WhenSupertypeIsNotInterfaceOrAbstractClass_ShouldNotTh var services = new ServiceCollection(); var assemblies = new[] { - typeof(TypeFinderTests).Assembly + typeof(CPluginServiceCollectionExtensionsTests).Assembly }; var serviceLifetime = ServiceLifetime.Transient;