Skip to content

Honor nullable reference annotations during generated dependency resolution #387

Description

@botoddly

GameKit.DependencyInjection currently generates GetRequiredService<T>() for every constructor and factory dependency except IEnumerable<T>. Consequently, a nullable dependency still behaves as required.

For example, GraphicsPipelineBuilder accepts Window? because it can build pipelines with explicit texture formats in a windowless container. Window is only needed by AddColorFormatFromDisplay(). Its registration therefore needs an otherwise unnecessary provider factory solely to call GetService<Window>():

AddTransient<GraphicsPipelineBuilder>(static provider => new GraphicsPipelineBuilder(
    provider.GetRequiredService<GpuDevice>(),
    provider.GetService<Window>(),
    provider.GetRequiredService<IShaderLoader>()));

The source generator should use nullable reference annotations when resolving generated constructor and factory arguments:

  • T and oblivious reference types: GetRequiredService<T>()
  • T?: GetService<T>()
  • IEnumerable<T>: retain the existing GetServices<T>() behavior

This should apply consistently to generated singleton and transient constructor injection, delegate factories, and instance factory methods.

Acceptance cases:

  • An unregistered nullable dependency is passed as null.
  • A registered nullable dependency is resolved normally, including from the requesting child provider.
  • An unregistered non-nullable dependency still throws.
  • GraphicsPipelineBuilder can be registered with AddTransient<GraphicsPipelineBuilder>() without making Window mandatory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions