-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Background
DependencyInjection.SourceGenerator currently generates registration code based on the [Register] attribute.
This works well for services where all constructor parameters can be resolved directly from the DI container.
However, some services require runtime values — such as IDs, file paths, or user-provided options — in addition to their injected dependencies.
In these cases, the generator currently produces registrations that fail at runtime, because the DI framework cannot provide those parameters automatically.
Problem
When a service constructor includes both DI-resolvable dependencies and parameters that must be supplied at runtime, the generator has no way to distinguish between them.
This means developers must currently:
- Manually write a factory class that combines DI and runtime arguments, or
- Add an
Initialize(...)method and perform a two-step construction.
Both approaches are inconsistent with the library’s goal of compile-time verified, single-phase registration.
Goal
Extend the source generator to support factory generation for services whose constructors include parameters that cannot be resolved from DI.
The goal is to let the generator automatically produce a factory that:
- Resolves DI dependencies using the container,
- Accepts runtime arguments explicitly,
- And returns a fully constructed instance of the target type.
The generated factory should always be registered as a singleton, since it only acts as a creation helper and has no per-instance state.
Concept
Developers would be able to mark specific constructor parameters to indicate that they should not be resolved from DI.
The generator would then:
- Detect constructors containing both DI and non-DI parameters.
- Generate a strongly-typed factory (interface + implementation, and optionally a delegate).
- Register the factory as a singleton service alongside the existing DI registrations.
The factory would internally use ActivatorUtilities.CreateInstance(...) (for Microsoft DI) or the equivalent for LightInject to combine container-resolved services with the runtime parameters.
Example scenario
[Register(typeof(IReportJob), Lifetime.Scoped)]
public sealed class ReportJob : IReportJob
{
public ReportJob(IRepository repository,
ILogger<ReportJob> logger,
[FactoryArgument] Guid reportId)
{
...
}
}Generated conceptually:
public interface IReportJobFactory
{
IReportJob Create(Guid reportId);
}
[GeneratedCode("DependencyInjection.SourceGenerator", "1.0.0.0")]
public sealed class ReportJobFactory : IReportJobFactory
{
private readonly IServiceProvider _sp;
public ReportJobFactory(IServiceProvider sp) => _sp = sp;
public IReportJob Create(Guid reportId) =>
ActivatorUtilities.CreateInstance<ReportJob>(_sp, reportId);
}
// Registration
services.AddSingleton<IReportJobFactory, ReportJobFactory>();Summary
This feature will make DependencyInjection.SourceGenerator more robust by allowing automatic factory generation for services that depend on both:
- Regular DI-injected services, and
- Explicit runtime arguments.
It eliminates the need for manual factories or post-construction initialization,
and ensures consistent, compile-time generated DI registration — even for mixed constructor scenarios.
All generated factories will be singleton by design.