Skip to content

Conversation

Copy link

Copilot AI commented Nov 6, 2025

Why this PR?

IVariantServiceProvider<T> eagerly instantiates all registered variant implementations when the provider is created, even when only one variant is actually used. This forces configuration and dependencies for unused variants to be available at startup.

Visible Changes

Services are now instantiated on-demand when the matching variant is resolved, not at provider creation time.

Implementation:

  • VariantServiceProvider<T> now accepts factory delegates instead of materialized service instances
  • Service descriptors are captured at registration time; instances are created lazily using ActivatorUtilities or user-provided factories
  • Type resolution for factory-based registrations is deferred until variant matching occurs

Example:

services.AddSingleton<ICalculator, DefaultCalculator>();
services.AddSingleton<ICalculator, RemoteCalculator>();  // Requires expensive dependencies
services.AddSingleton<ICalculator, CloudCalculator>();   // Requires cloud credentials

services.AddFeatureManagement()
    .WithVariantService<ICalculator>("CalculatorFeature");

// Only DefaultCalculator is instantiated if that's the active variant
// RemoteCalculator and CloudCalculator are never created
var calculator = await provider.GetServiceAsync(cancellationToken);

Backward compatible - all existing registration patterns (type, instance, factory) are supported.

Original prompt

This section details on the original issue you should resolve

<issue_title>Lazy VariantServiceProvider</issue_title>
<issue_description>Currently, when you use IVariantServiceProvider to resolve a service type variant it instantiates all configured service variants prior to resolve the selected one.
Ideally we'd want to lazy instantiate the resolved service only.

My use case is, I've got several implementations for a given interface, each requires a unique set of configuration properties and dependencies. If I configure my app to always resolve to a single variant I don't want to have all settings and dependencies available for the other implementations that I'm not using.

At the moment all my implementations must be configured and they are all loaded into memory prior to resolve the instance.</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits November 6, 2025 09:47
Co-authored-by: zhiyuanliang-ms <141655842+zhiyuanliang-ms@users.noreply.github.com>
… comments

Co-authored-by: zhiyuanliang-ms <141655842+zhiyuanliang-ms@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement lazy instantiation for VariantServiceProvider Implement lazy instantiation for VariantServiceProvider Nov 6, 2025
Copilot finished work on behalf of zhiyuanliang-ms November 6, 2025 09:56
Copilot AI requested a review from zhiyuanliang-ms November 6, 2025 09:56

// Capture the service descriptors before the service provider is built
// This allows us to create factories without instantiating services eagerly
List<ServiceDescriptor> serviceDescriptors = builder.Services
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is no guaranteed that the TService has been registered when WithVariantService is called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lazy VariantServiceProvider

2 participants