Skip to content

fix: dotnet generated code dependency injection issue #208

@tomflenner

Description

@tomflenner

Description

The generated .NET code produces a dependency injection configuration that causes a runtime exception due to a type mismatch between the registered service type and the constructor dependency.

Current Behavior

The code generator creates an AddOpenFeature extension method that registers a FeatureClient without specifying the interface type:

public static IServiceCollection AddOpenFeature(this IServiceCollection services)
{
    return services
        .AddSingleton(_ => Api.Instance)
        .AddSingleton(provider => provider.GetRequiredService<Api>().GetClient())
        .AddSingleton<GeneratedClient>();
}

The problematic line:

.AddSingleton(provider => provider.GetRequiredService<Api>().GetClient())

This registers FeatureClient (the concrete type returned by GetClient()) as the service type:

public FeatureClient GetClient(string? name = null, string? version = null, ILogger? logger = null,
    EvaluationContext? context = null) =>
    new FeatureClient(this, () => this._repository.GetProvider(name), name, version, logger, context);

However, GeneratedClient expects IFeatureClient in its constructor:

public class GeneratedClient
{
    private readonly IFeatureClient _client;

    public GeneratedClient(IFeatureClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }
}

Error

Unhandled exception. System.InvalidOperationException: Unable to resolve service for type 'OpenFeature.IFeatureClient' while attempting to activate 'OpenFeatureGeneratedClient.GeneratedClient'

Expected Behavior

The dependency injection container should be able to resolve IFeatureClient when constructing GeneratedClient.

Proposed Solution

Update the generated code to explicitly register the service with both the interface and implementation types:

public static IServiceCollection AddOpenFeature(this IServiceCollection services)
{
    return services
        .AddSingleton(_ => Api.Instance)
        .AddSingleton<IFeatureClient, FeatureClient>(provider => provider.GetRequiredService<Api>().GetClient())
        .AddSingleton<GeneratedClient>();
}

This change:

  • Follows the dependency inversion principle by registering against the interface
  • Maintains compatibility with the existing GeneratedClient constructor
  • Allows proper resolution of IFeatureClient from the DI container

Reproduction

Repository with reproduction case and fixed version: https://github.com/tomflenner/openfeature-cli-dotnet-issue-208

Environment

  • OpenFeature CLI version: v0.3.14
  • .NET version: 10.0.102

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions