0Pricing
C# Academy · Leçon

Patrons Factory et Options

Utilisez des délégués d’usine, IServiceProvider et le patron Options pour gérer des dépendances conditionnelles ou configurables.

Patrons Factory et Options est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.

Quand l’injection par constructeur ne suffit pas

Vous devez parfois créer des services de manière conditionnelle, en fonction de données d’exécution, ou les configurer différemment selon le cas d’utilisation. C’est là que les modèles de fabrique et des options sont particulièrement utiles.

Délégués de fabrique avec AddTransient

Vous pouvez transmettre un délégué de fabrique à AddTransient, AddScoped ou AddSingleton. Le délégué reçoit IServiceProvider, ce qui vous permet de résoudre d’autres services.

builder.Services.AddTransient<IPaymentGateway>(sp =>
{
    var config = sp.GetRequiredService<IOptions<PaymentConfig>>().Value;
    return config.Provider == "stripe"
        ? new StripeGateway(config.ApiKey)
        : new PayPalGateway(config.ClientId, config.Secret);
});

Options nommées avec IOptionsSnapshot

Le modèle des options lie les sections de configuration à des classes fortement typées. Utilisez IOptions<T> pour les services à instance unique et IOptionsSnapshot<T> pour des valeurs actualisées à chaque requête.

public class SmtpSettings
{
    public string Host { get; set; } = "";
    public int Port { get; set; } = 587;
    public string Username { get; set; } = "";
}

// Registration
builder.Services.Configure<SmtpSettings>(
    builder.Configuration.GetSection("Smtp"));

// Consumption
public class EmailService
{
    private readonly SmtpSettings _settings;
    public EmailService(IOptions<SmtpSettings> opts)
        => _settings = opts.Value;
}

IOptionsMonitor pour le rechargement à chaud

IOptionsMonitor<T> fournit la valeur actuelle de l’option au moment de l’accès et vous avertit lorsque la configuration change : c’est idéal pour les services à instance unique qui doivent prendre en compte les mises à jour de configuration en direct.

public class FeatureFlagService
{
    private readonly IOptionsMonitor<FeatureFlags> _monitor;

    public FeatureFlagService(IOptionsMonitor<FeatureFlags> monitor)
        => _monitor = monitor;

    public bool IsEnabled(string flag)
    {
        // Always reads the latest config value
        return _monitor.CurrentValue.Flags.GetValueOrDefault(flag);
    }
}

Options nommées

Les options nommées vous permettent d’enregistrer plusieurs configurations du même type. Utilisez Configure<T>(name, ...), puis résolvez-les avec IOptionsSnapshot<T>.Get(name).

builder.Services.Configure<S3Settings>("primary",
    builder.Configuration.GetSection("S3:Primary"));
builder.Services.Configure<S3Settings>("backup",
    builder.Configuration.GetSection("S3:Backup"));

public class S3Service
{
    public S3Service(IOptionsSnapshot<S3Settings> opts)
    {
        var primary = opts.Get("primary");
        var backup  = opts.Get("backup");
    }
}

Valider les options au démarrage

Utilisez ValidateDataAnnotations() ou un validateur personnalisé pour vous assurer que la configuration est correcte avant le démarrage de l’application. Combinez cette validation avec ValidateOnStart() pour faire échouer l’application immédiatement en cas de problème.

public class SmtpSettings
{
    [Required] public string Host { get; set; } = "";
    [Range(1, 65535)] public int Port { get; set; } = 587;
}

builder.Services
    .AddOptions<SmtpSettings>()
    .Bind(builder.Configuration.GetSection("Smtp"))
    .ValidateDataAnnotations()
    .ValidateOnStart();

Modèle de fabrique abstraite

Une interface de fabrique abstraite vous permet d’injecter une fabrique dans les services et de retarder la construction jusqu’à ce que les données d’exécution soient disponibles, sans créer de dépendance directe envers IServiceProvider.

public interface IReportFactory
{
    IReport Create(string reportType);
}

public class ReportFactory : IReportFactory
{
    private readonly IServiceProvider _sp;
    public ReportFactory(IServiceProvider sp) => _sp = sp;

    public IReport Create(string reportType) => reportType switch
    {
        "pdf"  => _sp.GetRequiredService<PdfReport>(),
        "excel"=> _sp.GetRequiredService<ExcelReport>(),
        _      => throw new ArgumentException("Unknown type")
    };
}

builder.Services.AddTransient<IReportFactory, ReportFactory>();

Services avec clé (.NET 8)

.NET 8 introduit les services avec clé : vous pouvez enregistrer plusieurs implémentations sous des clés différentes et résoudre la bonne avec [FromKeyedServices] ou GetKeyedService.

builder.Services.AddKeyedScoped<IPaymentGateway, StripeGateway>("stripe");
builder.Services.AddKeyedScoped<IPaymentGateway, PayPalGateway>("paypal");

// Resolve in a class:
public class CheckoutService(
    [FromKeyedServices("stripe")] IPaymentGateway stripe,
    [FromKeyedServices("paypal")]  IPaymentGateway paypal) { }

PostConfigure pour les remplacements

PostConfigure s’exécute après tous les appels à Configure. Utilisez-le pour appliquer des remplacements dans les tests ou imposer des invariants, quelle que soit la configuration chargée.

// In integration tests: force test values after real config
builder.Services.PostConfigure<SmtpSettings>(opts =>
{
    opts.Host = "smtp.test.local";
    opts.Port = 25;
});

Méthodes d’extension de IServiceCollection

Regroupez vos enregistrements dans des méthodes d’extension afin de garder Program.cs clair et de rendre les modules réutilisables dans plusieurs projets.

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddPaymentServices(
        this IServiceCollection services,
        IConfiguration config)
    {
        services.Configure<PaymentConfig>(config.GetSection("Payment"));
        services.AddScoped<IPaymentGateway, StripeGateway>();
        services.AddScoped<PaymentService>();
        return services;
    }
}

// Usage in Program.cs:
builder.Services.AddPaymentServices(builder.Configuration);

Cas concret : notifications multi-fournisseurs

En utilisant ensemble une fabrique et des options nommées, vous pouvez sélectionner le fournisseur de notifications approprié à l’exécution, selon la préférence de l’utilisateur enregistrée dans la base de données.

builder.Services.AddKeyedScoped<INotifier, EmailNotifier>("email");
builder.Services.AddKeyedScoped<INotifier, SmsNotifier>("sms");
builder.Services.AddKeyedScoped<INotifier, PushNotifier>("push");

public class NotificationService
{
    private readonly IServiceProvider _sp;
    public NotificationService(IServiceProvider sp) => _sp = sp;

    public Task SendAsync(string channel, string message)
    {
        var notifier = _sp.GetRequiredKeyedService<INotifier>(channel);
        return notifier.SendAsync(message);
    }
}

Vérification rapide

Quelle interface fournit la valeur actuelle des options AND avertit lors des changements de configuration, ce qui la rend adaptée aux services à instance unique ?

Récapitulatif : modèles de fabrique et d’options

Points essentiels :

  • Les délégués de fabrique dans les méthodes Add* permettent de créer des services conditionnellement ou selon la configuration d’exécution
  • Le modèle des options lie les sections de configuration à des objets POCO fortement typés
  • IOptions = statique, IOptionsSnapshot = par requête, IOptionsMonitor = mises à jour en direct
  • Validez les options au démarrage avec ValidateDataAnnotations().ValidateOnStart()
  • Les services avec clé (.NET 8) remplacent les solutions de contournement fondées sur des fabriques pour les implémentations nommées

Questions Fréquemment Posées

La leçon « Patrons Factory et Options » est-elle gratuite ?

Oui — le texte complet de « Patrons Factory et Options » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Patrons Factory et Options » ?

Utilisez des délégués d’usine, IServiceProvider et le patron Options pour gérer des dépendances conditionnelles ou configurables. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer C# Academy ?

Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Patrons Factory et Options » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?

Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Fondamentaux des conteneurs DI
  2. Durées de vie des services : Transient, Scoped, Singleton
  3. Injection par constructeur et interfaces
  4. Patrons Factory et Options
← Retour à C# Academy