-
Notifications
You must be signed in to change notification settings - Fork 126
Expand file tree
/
Copy pathFeatureManagementBuilderExtensions.cs
More file actions
125 lines (113 loc) · 6.66 KB
/
Copy pathFeatureManagementBuilderExtensions.cs
File metadata and controls
125 lines (113 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.FeatureManagement.FeatureFilters;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.FeatureManagement
{
/// <summary>
/// Extensions used to add feature management functionality.
/// </summary>
public static class FeatureManagementBuilderExtensions
{
/// <summary>
/// Adds an <see cref="ITargetingContextAccessor"/> to be used for targeting and registers the targeting filter to the feature management system.
/// </summary>
/// <param name="builder">The <see cref="IFeatureManagementBuilder"/> used to customize feature management functionality.</param>
/// <returns>A <see cref="IFeatureManagementBuilder"/> that can be used to customize feature management functionality.</returns>
public static IFeatureManagementBuilder WithTargeting<T>(this IFeatureManagementBuilder builder) where T : ITargetingContextAccessor
{
//
// Register the targeting context accessor with the same lifetime as the feature manager
if (builder.Services.Any(descriptor => descriptor.ServiceType == typeof(IFeatureManager) && descriptor.Lifetime == ServiceLifetime.Scoped))
{
builder.Services.TryAddScoped(typeof(ITargetingContextAccessor), typeof(T));
}
else
{
builder.Services.TryAddSingleton(typeof(ITargetingContextAccessor), typeof(T));
}
builder.AddFeatureFilter<TargetingFilter>();
return builder;
}
/// <summary>
/// Adds a <see cref="VariantServiceProvider{TService}"/> to the feature management system.
/// </summary>
/// <param name="builder">The <see cref="IFeatureManagementBuilder"/> used to customize feature management functionality.</param>
/// <param name="featureName">The feature flag that should be used to determine which variant of the service should be used. The <see cref="VariantServiceProvider{TService}"/> will return different implementations of TService according to the assigned variant.</param>
/// <returns>A <see cref="IFeatureManagementBuilder"/> that can be used to customize feature management functionality.</returns>
/// <exception cref="ArgumentNullException">Thrown if feature name parameter is null.</exception>
/// <exception cref="InvalidOperationException">Thrown if a variant service of the type has already been added.</exception>
public static IFeatureManagementBuilder WithVariantService<TService>(this IFeatureManagementBuilder builder, string featureName) where TService : class
{
if (string.IsNullOrEmpty(featureName))
{
throw new ArgumentNullException(nameof(featureName));
}
if (builder.Services.Any(descriptor => descriptor.ServiceType == typeof(IVariantServiceProvider<TService>)))
{
throw new InvalidOperationException($"A variant service of {typeof(TService).FullName} has already been added.");
}
if (builder.Services.Any(descriptor => descriptor.ServiceType == typeof(IFeatureManager) && descriptor.Lifetime == ServiceLifetime.Scoped))
{
builder.Services.AddScoped<IVariantServiceProvider<TService>>(sp => new VariantServiceProvider<TService>(
featureName,
sp.GetRequiredService<IVariantFeatureManager>(),
sp));
}
else
{
builder.Services.AddSingleton<IVariantServiceProvider<TService>>(sp => new VariantServiceProvider<TService>(
featureName,
sp.GetRequiredService<IVariantFeatureManager>(),
sp));
}
return builder;
}
/// <summary>
/// Adds a <see cref="FeatureServiceProvider{TService,TEnabled,TDisabled}"/> to the feature management system.
/// </summary>
/// <param name="builder">The <see cref="IFeatureManagementBuilder"/> used to customize feature management functionality.</param>
/// <param name="featureName">The feature flag that should be used to determine which implementation of the service should be used. The <see cref="IFeatureServiceProvider{TService}"/> will return different implementations of TService according to the feature status.</param>
/// <param name="options">Options used to configure the feature service provider.</param>
/// <returns>A <see cref="IFeatureManagementBuilder"/> that can be used to customize feature management functionality.</returns>
/// <exception cref="ArgumentNullException">Thrown if feature name parameter is null.</exception>
/// <exception cref="InvalidOperationException">Thrown if a feature service of the type has already been added.</exception>
public static IFeatureManagementBuilder WithFeatureService<TService, TEnabled, TDisabled>(this IFeatureManagementBuilder builder, string featureName, FeatureServiceProviderOptions options = null)
where TService : class
where TEnabled : class, TService
where TDisabled : class, TService
{
if (string.IsNullOrEmpty(featureName))
{
throw new ArgumentNullException(nameof(featureName));
}
options ??= new FeatureServiceProviderOptions();
if (builder.Services.Any(descriptor => descriptor.ServiceType == typeof(IFeatureServiceProvider<TService>)))
{
throw new InvalidOperationException($"A feature service of {typeof(TService).FullName} has already been added.");
}
if (builder.Services.Any(descriptor => descriptor.ServiceType == typeof(IFeatureManager) && descriptor.Lifetime == ServiceLifetime.Scoped))
{
builder.Services.AddScoped<IFeatureServiceProvider<TService>>(sp => new FeatureServiceProvider<TService, TEnabled, TDisabled>(
sp,
sp.GetRequiredService<IFeatureManager>(),
featureName,
options));
}
else
{
builder.Services.AddSingleton<IFeatureServiceProvider<TService>>(sp => new FeatureServiceProvider<TService, TEnabled, TDisabled>(
sp,
sp.GetRequiredService<IFeatureManager>(),
featureName,
options));
}
return builder;
}
}
}