Summary
Generated factory files reference four BCL types unqualified — Task, CancellationToken, IServiceProvider, InvalidOperationException — but emit no using System;, using System.Threading;, or using System.Threading.Tasks;. They resolve today only because the consuming project has ImplicitUsings enabled. A consumer that does not (an older-style project file, or one that sets <ImplicitUsings>disable</ImplicitUsings>) gets CS0246 inside *.g.cs files it cannot edit.
Mechanism
The factory header is fixed at FactoryGenerator.Types.cs:171-173, with two more usings appended for the class leg (ClassFactoryRenderer.cs:42,48):
using Neatoo.RemoteFactory;
using Neatoo.RemoteFactory.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection.Extensions;
No using System* is emitted anywhere in the generator (grep -rn '"using System' src/Generator returns nothing), while the renderers emit those four types by bare name:
| Type |
Namespace |
Emitted at |
IServiceProvider |
System |
ClassFactoryRenderer.cs:172,250,264 |
InvalidOperationException |
System |
ClassFactoryRenderer.cs:398 (the IsServerRuntime guard) |
CancellationToken |
System.Threading |
ClassFactoryRenderer.cs:1241,1278,1285,1292 and every interface member |
Task, Task.FromResult |
System.Threading.Tasks |
ClassFactoryRenderer.cs:598,602,1005,1009,1124,1220 |
Consumer types are not affected: generated code sits in the consumer's own namespace, so IOrder and friends resolve without a using.
Reproduction
Observed 2026-09-08 during EXRM-004, in the generator's own unit-test harness rather than a consumer build. DiagnosticTestHelper.RunGenerator (src/Tests/RemoteFactory.UnitTests/TestContainers/DiagnosticTestHelper.cs:71-88) builds a raw CSharpCompilation from the fixture source with no implicit usings — the same position as a consumer with the feature off. Adding an output-compilation assertion to two NF0105 tests surfaced it immediately:
TestNamespace.StaticFactoryTargetFactory.g.cs(24,26): error CS0246: The type or namespace name 'IServiceProvider' could not be found
TestNamespace.StaticFactoryTargetFactory.g.cs(43,64): error CS0246: The type or namespace name 'CancellationToken' could not be found
TestNamespace.StaticFactoryTargetFactory.g.cs(57,27): error CS0246: The type or namespace name 'InvalidOperationException' could not be found
The errors disappeared once the fixture source declared using System;, using System.Threading;, using System.Threading.Tasks; itself — which is why AssemblyAttributeEmissionTests already carries the note "The usings are required, not decorative" on its fixtures (AssemblyAttributeEmissionTests.cs:311-318).
Not observed in a real consumer build. Every project in this repository, and every .NET SDK template since .NET 6, enables ImplicitUsings, so the gap has never surfaced outside the test harness. That is what makes this latent rather than urgent — but it is a compile error in unfixable generated code when it does surface, and the diagnosis (CS0246 in a .g.cs file) points the user at the wrong place.
Suggested fix
Either would close it:
- Emit the three usings in the factory header alongside the existing five. Smallest change; consistent with how the header already works.
- Global-qualify the BCL tokens (
global::System.Threading.Tasks.Task<…>, etc.). More verbose output, but it matches the convention the relay-handler leg already follows — FactoryGenerator.RelayHandler.cs qualifies every emitted type token, pinned by AssemblyAttributeEmissionTests.RelayHandler_EveryEmittedTypeToken_IsGlobalQualified (:993-1013), precisely so the generated body does not depend on the file's usings.
Option 2 is the stronger guarantee and the one the codebase has already reached for once; option 1 is the smaller diff. Either wants a regression test that compiles generated output from a fixture with no usings beyond Neatoo.RemoteFactory.
Context
Surfaced by EXRM-004 (PR #96) while hardening two NF0105 tests against silent generator failures; recorded there as a dismissed finding (pre-existing, serving none of that todo's criteria) and filed here instead.
Summary
Generated factory files reference four BCL types unqualified —
Task,CancellationToken,IServiceProvider,InvalidOperationException— but emit nousing System;,using System.Threading;, orusing System.Threading.Tasks;. They resolve today only because the consuming project hasImplicitUsingsenabled. A consumer that does not (an older-style project file, or one that sets<ImplicitUsings>disable</ImplicitUsings>) getsCS0246inside*.g.csfiles it cannot edit.Mechanism
The factory header is fixed at
FactoryGenerator.Types.cs:171-173, with two more usings appended for the class leg (ClassFactoryRenderer.cs:42,48):No
using System*is emitted anywhere in the generator (grep -rn '"using System' src/Generatorreturns nothing), while the renderers emit those four types by bare name:IServiceProviderSystemClassFactoryRenderer.cs:172,250,264InvalidOperationExceptionSystemClassFactoryRenderer.cs:398(theIsServerRuntimeguard)CancellationTokenSystem.ThreadingClassFactoryRenderer.cs:1241,1278,1285,1292and every interface memberTask,Task.FromResultSystem.Threading.TasksClassFactoryRenderer.cs:598,602,1005,1009,1124,1220Consumer types are not affected: generated code sits in the consumer's own namespace, so
IOrderand friends resolve without a using.Reproduction
Observed 2026-09-08 during EXRM-004, in the generator's own unit-test harness rather than a consumer build.
DiagnosticTestHelper.RunGenerator(src/Tests/RemoteFactory.UnitTests/TestContainers/DiagnosticTestHelper.cs:71-88) builds a rawCSharpCompilationfrom the fixture source with no implicit usings — the same position as a consumer with the feature off. Adding an output-compilation assertion to two NF0105 tests surfaced it immediately:The errors disappeared once the fixture source declared
using System;,using System.Threading;,using System.Threading.Tasks;itself — which is whyAssemblyAttributeEmissionTestsalready carries the note "The usings are required, not decorative" on its fixtures (AssemblyAttributeEmissionTests.cs:311-318).Not observed in a real consumer build. Every project in this repository, and every .NET SDK template since .NET 6, enables
ImplicitUsings, so the gap has never surfaced outside the test harness. That is what makes this latent rather than urgent — but it is a compile error in unfixable generated code when it does surface, and the diagnosis (CS0246in a.g.csfile) points the user at the wrong place.Suggested fix
Either would close it:
global::System.Threading.Tasks.Task<…>, etc.). More verbose output, but it matches the convention the relay-handler leg already follows —FactoryGenerator.RelayHandler.csqualifies every emitted type token, pinned byAssemblyAttributeEmissionTests.RelayHandler_EveryEmittedTypeToken_IsGlobalQualified(:993-1013), precisely so the generated body does not depend on the file's usings.Option 2 is the stronger guarantee and the one the codebase has already reached for once; option 1 is the smaller diff. Either wants a regression test that compiles generated output from a fixture with no usings beyond
Neatoo.RemoteFactory.Context
Surfaced by EXRM-004 (PR #96) while hardening two NF0105 tests against silent generator failures; recorded there as a dismissed finding (pre-existing, serving none of that todo's criteria) and filed here instead.