Fix System.TypeLoadException in NukedBit.NRepo global tool#127188
Fix System.TypeLoadException in NukedBit.NRepo global tool#127188
Conversation
…prevent TypeLoadException Adds a default interface method (DIM) for the Func-based UseServiceProviderFactory overload in IHostBuilder for .NET Core targets. This prevents TypeLoadException when loading old IHostBuilder implementations (e.g., from Microsoft.Extensions.Hosting v2.2.0.0) that only implement the non-Func overload on .NET 11+. The DIM is not added for .NET Standard or .NET Framework targets since we don't need backward compat shims there. Fixes: TypeLoadException in NukedBit.NRepo and other tools using old Hosting assemblies. Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/186bed25-e477-43a0-ab1f-660ba8bc7769 Co-authored-by: ericstj <8918108+ericstj@users.noreply.github.com>
… DIM Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/186bed25-e477-43a0-ab1f-660ba8bc7769 Co-authored-by: ericstj <8918108+ericstj@users.noreply.github.com>
|
@copilot can you address feedback and fix the PR description to be an appropriate summary, and mention that it fixes issue #126994. |
…mentations to override Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/bb09ea95-ca82-4973-92b7-3d829aa23711 Co-authored-by: ericstj <8918108+ericstj@users.noreply.github.com>
Done. Removed the DIM body from the reference assembly (dd524cb) and updated the PR description to be a proper summary mentioning the fix for #126994. |
|
Tagging subscribers to this area: @dotnet/area-extensions-hosting |
There was a problem hiding this comment.
Pull request overview
This PR addresses a runtime TypeLoadException when older IHostBuilder implementations (pre-v3.0 interface shape) are loaded on modern .NET by introducing a .NET-only default interface method (DIM) for the newer UseServiceProviderFactory(Func<...>) overload, and adding tests to validate the fallback behavior.
Changes:
- Add a
#if NETDIM implementation forIHostBuilder.UseServiceProviderFactory(Func<HostBuilderContext, IServiceProviderFactory<T>>)that null-checks and throwsNotSupportedExceptionwhen used as fallback. - Update the test project to compile against the implementation assembly (not the ref assembly) so the DIM body can be exercised.
- Add
#if NETtests validating the DIM fallback throws, null argument behavior, and that the non-Func overload remains callable.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/IHostBuilder.cs | Adds a .NET-only DIM body for the Func-based overload to prevent type-load failures for older implementations. |
| src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/Microsoft.Extensions.Hosting.Abstractions.Tests.csproj | Switches the project reference to skip ref assemblies so tests can compile/run against the DIM implementation. |
| src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostBuilderContextTests.cs | Adds #if NET tests covering DIM fallback behavior and argument validation. |
🤖 Copilot Code Review — PR #127188Note This review was generated by Copilot and validated across multiple AI models (Claude Opus 4.6, GPT-5.3-Codex, extensions-reviewer agent). All models reached the same conclusions on key findings. Holistic AssessmentMotivation: Justified. This fixes a real regression (#126994) where old Approach: Correct. Adding a DIM is the standard .NET pattern for backward-compatible interface evolution. The design is well-considered: old binaries get a graceful Summary: ✅ LGTM. The DIM implementation is correct, the ref assembly handling is intentional and appropriate, and the tests cover the key scenarios. Two minor documentation suggestions below are non-blocking. Detailed Findings✅ DIM Pattern — Correct and well-designedThe
Both existing ✅ Ref Assembly — Intentionally kept abstractThe ref assembly retains the plain abstract signature (no DIM body). This means new code compiled against the latest SDK is still required to implement the method — the DIM only serves as a runtime fallback for old pre-compiled binaries. This is the correct choice given that this method is functionally required for proper hosting behavior. ✅ Test Coverage — Adequate for the DIM behaviorThe three tests cover the key scenarios: DIM throws ✅ csproj Change — CorrectMerging the two 💡 Missing
|
Fixes a
TypeLoadExceptionthrown when loading oldIHostBuilderimplementations (e.g. fromMicrosoft.Extensions.Hostingv2.2.0.0) on .NET 11. These old assemblies lack theUseServiceProviderFactory(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>>)overload added in v3.0, causing the .NET type-loader to reject them at class-load time.Description
Root Cause
IHostBuilder.UseServiceProviderFactory(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>>)was added in v3.0. Old assemblies implementing only the v2.x interface shape fail the .NET type-loader check that all interface members are implemented, resulting in aTypeLoadException.Fix
Adds a Default Interface Method (DIM) for the Func-based overload, guarded by
#if NET:TypeLoadExceptionfactory(throwingArgumentNullException) then throwsNotSupportedExceptionwith the concrete type name if actually invokedHostBuilder,HostApplicationBuilder) explicitly override this method and are unaffected — explicit overrides always win over DIMs.NET Standard/.NET Frameworktargets are unchanged (DIMs aren't supported there)The reference assembly intentionally keeps the plain abstract signature (no DIM body) so that new code compiling against the latest reference is still required to implement the method.
Changes
src/IHostBuilder.cs— adds DIM withArgumentNullException.ThrowIfNullguard,NotSupportedException, and<exception>XML doc under#if NETref/Microsoft.Extensions.Hosting.Abstractions.cs— retains plain abstract signature (no DIM body) so callers compiling against the latest reference must still implement the methodtests/HostBuilderContextTests.cs— adds 3 tests under#if NETcovering:NotSupportedExceptionwhen DIM is the fallback,ArgumentNullExceptionfor nullfactory, and that the non-Funcoverload is unaffectedTesting
UseServiceProviderFactory_FuncOverload_WithoutOverride_ThrowsNotSupportedExceptionUseServiceProviderFactory_FuncOverload_WithNullFactory_ThrowsArgumentNullExceptionUseServiceProviderFactory_NonFuncOverload_WithoutDIM_CanBeImplementedAndCalled