-
Notifications
You must be signed in to change notification settings - Fork 114
Introduce ServiceProviderLifetimeType for scoped dependency container #998
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4d9456b
95086f7
69a32bd
3e95209
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,59 +3,103 @@ | |
| using System.Linq; | ||
| using System.Reflection; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Reqnroll.Bindings.Discovery; | ||
| using Reqnroll.Infrastructure; | ||
|
|
||
| namespace Reqnroll.Microsoft.Extensions.DependencyInjection | ||
| { | ||
| public class ServiceCollectionFinder : IServiceCollectionFinder | ||
| { | ||
| private readonly ITestRunnerManager testRunnerManager; | ||
| private (IServiceCollection, ScopeLevelType) _cache; | ||
| private readonly ITestRunnerManager _testRunnerManager; | ||
| private readonly IRuntimeBindingRegistryBuilder _bindingRegistryBuilder; | ||
| private readonly ITestAssemblyProvider _testAssemblyProvider; | ||
| private (IServiceCollection ServiceCollection, ScenarioDependenciesAttribute Attribute) _cache; | ||
| private readonly object _cacheLock = new(); | ||
|
|
||
| public ServiceCollectionFinder(ITestRunnerManager testRunnerManager) | ||
| public ServiceCollectionFinder(ITestRunnerManager testRunnerManager, IRuntimeBindingRegistryBuilder bindingRegistryBuilder, ITestAssemblyProvider testAssemblyProvider) | ||
| { | ||
| this.testRunnerManager = testRunnerManager; | ||
| _testRunnerManager = testRunnerManager; | ||
| _bindingRegistryBuilder = bindingRegistryBuilder; | ||
| _testAssemblyProvider = testAssemblyProvider; | ||
| } | ||
|
|
||
| public ServiceProviderLifetimeType GetServiceProviderLifetime() | ||
| { | ||
| if (_cache == default) | ||
| { | ||
| PopulateCache(); | ||
| } | ||
|
|
||
| return _cache.Attribute.ServiceProviderLifetime; | ||
| } | ||
|
|
||
| public (IServiceCollection, ScopeLevelType) GetServiceCollection() | ||
| { | ||
| if (_cache == default) | ||
| { | ||
| PopulateCache(); | ||
| } | ||
|
|
||
| return (_cache.ServiceCollection, _cache.Attribute.ScopeLevel); | ||
| } | ||
|
|
||
| private void PopulateCache() | ||
| { | ||
| if (_cache != default) | ||
| { | ||
| return _cache; | ||
| return; | ||
| } | ||
|
Comment on lines
+46
to
51
|
||
|
|
||
| var assemblies = testRunnerManager.BindingAssemblies; | ||
| foreach (var assembly in assemblies) | ||
| lock (_cacheLock) | ||
| { | ||
| foreach (var type in assembly.GetTypes()) | ||
| if (_cache != default) | ||
| { | ||
| foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) | ||
| { | ||
| var scenarioDependenciesAttribute = (ScenarioDependenciesAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(ScenarioDependenciesAttribute)); | ||
| return; | ||
| } | ||
|
|
||
| if (scenarioDependenciesAttribute != null) | ||
| var assemblies = _testRunnerManager.BindingAssemblies ?? _bindingRegistryBuilder.GetBindingAssemblies(_testAssemblyProvider.TestAssembly); | ||
| foreach (var assembly in assemblies) | ||
| { | ||
| foreach (var type in assembly.GetTypes()) | ||
| { | ||
| foreach (var methodInfo in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) | ||
| { | ||
| var serviceCollection = GetServiceCollection(methodInfo); | ||
| if (scenarioDependenciesAttribute.AutoRegisterBindings) | ||
| var scenarioDependenciesAttribute = (ScenarioDependenciesAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(ScenarioDependenciesAttribute)); | ||
|
|
||
| if (scenarioDependenciesAttribute != null) | ||
| { | ||
| AddBindingAttributes(assemblies, serviceCollection); | ||
| var serviceCollection = GetServiceCollection(methodInfo); | ||
| if (scenarioDependenciesAttribute.AutoRegisterBindings) | ||
| { | ||
| AddBindingAttributes(assemblies, serviceCollection); | ||
| } | ||
|
|
||
| // If the ServiceProviderLifetime is Scenario, set the ScopeLevel to Scenario to match. | ||
| if (scenarioDependenciesAttribute.ServiceProviderLifetime == ServiceProviderLifetimeType.Scenario) | ||
| { | ||
| scenarioDependenciesAttribute.ScopeLevel = ScopeLevelType.Scenario; | ||
| } | ||
|
|
||
| _cache = (serviceCollection, scenarioDependenciesAttribute); | ||
| return; | ||
| } | ||
| return _cache = (serviceCollection, scenarioDependenciesAttribute.ScopeLevel); | ||
| } | ||
| } | ||
| } | ||
| var assemblyNames = assemblies.Select(a => a.GetName().Name).ToList(); | ||
| throw new MissingScenarioDependenciesException(assemblyNames); | ||
| } | ||
| var assemblyNames = assemblies.Select(a => a.GetName().Name).ToList(); | ||
| throw new MissingScenarioDependenciesException(assemblyNames); | ||
| } | ||
|
|
||
| private static IServiceCollection GetServiceCollection(MethodInfo methodInfo) | ||
| { | ||
| var serviceCollection = methodInfo.Invoke(null, null); | ||
| if(methodInfo.ReturnType == typeof(void)) | ||
| if (methodInfo.ReturnType == typeof(void)) | ||
| { | ||
| throw new InvalidScenarioDependenciesException("the method doesn't return a value."); | ||
| } | ||
|
|
||
| var serviceCollection = methodInfo.Invoke(null, null); | ||
|
|
||
| if (serviceCollection == null) | ||
| { | ||
| throw new InvalidScenarioDependenciesException("returned null."); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new CustomizeTestThreadDependenciesEventHandler method lacks any test coverage. Since this is a new method that handles the TestThread lifetime configuration, it should have corresponding tests to verify that the RootServiceProviderContainer is registered correctly when ServiceProviderLifetime is set to TestThread.