Keep externally set ServiceProvider when ConfigureGlobalOptions triggers a rebuild - #252
Open
cytoph wants to merge 1 commit into
Open
Keep externally set ServiceProvider when ConfigureGlobalOptions triggers a rebuild#252cytoph wants to merge 1 commit into
cytoph wants to merge 1 commit into
Conversation
…ers a rebuild ConfigureGlobalOptions sets isRequireCallBuildAndSetServiceProvider, which made the generated BuildAndSetServiceProvider build an empty ServiceCollection and replace a ServiceProvider that was already set externally (e.g. by the hosting integration's ToConsoleAppBuilder), silently breaking DI. The generated BuildAndSetServiceProvider now returns early when ConsoleApp.ServiceProvider is already set and nothing DI-related was configured on the builder itself.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #251
Problem
When combining the hosting integration with global options, DI breaks silently:
ConfigureGlobalOptionssetsisRequireCallBuildAndSetServiceProvider = true, so the generatedBuildAndSetServiceProviderruns duringRunAsync, builds an emptyServiceCollection(nothing was configured on the builder itself - the services live in the host), and replaces the ServiceProvider thatToConsoleAppBuilderhad already set. Constructor dependencies then resolve tonulland blow up withNullReferenceExceptionon first use.Fix
The generated
BuildAndSetServiceProvidernow returns early whenConsoleApp.ServiceProvideris already set and nothing DI-related was configured on the builder itself (configureServices,createServiceProvider,postConfigureServices, andconfigureLoggingwhere applicable, all null). The flag-set inConfigureGlobalOptionsis left untouched, because the flag also gates global-options parsing in the generatedRunpath for context-less commands.Generated code (with DependencyInjection referenced) now begins:
Behavior when a provider was configured on the builder (or none was set externally) is unchanged.
Test
DITest.ConfigureGlobalOptionsKeepsExternallySetServiceProviderreproduces the issue with a pre-setServiceProviderplusConfigureGlobalOptionsand asserts that the service still resolves and the global option is still parsed. It fails without the fix and passes with it.Since the DI emit path (
DllReference.HasDependencyInjection) had no coverage in GeneratorTests, the runner gained an optionaladditionalReferencesparameter and the test project referencesMicrosoft.Extensions.DependencyInjection8.0.1 (8.x on purpose: its net8.0 lib matches the runner's .NET 8 reference assemblies; 9.x triggers CS1705).🤖 Generated with Claude Code