Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions examples/ConsoleApp/FeatureFilters/AccountIdFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Microsoft.FeatureManagement;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Consoto.Banking.AccountService.FeatureManagement
Expand All @@ -18,7 +17,7 @@ namespace Consoto.Banking.AccountService.FeatureManagement
[FilterAlias("AccountId")]
class AccountIdFilter : IContextualFeatureFilter<IAccountContext>
{
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureEvaluationContext, IAccountContext accountContext, CancellationToken _)
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureEvaluationContext, IAccountContext accountContext)
{
if (string.IsNullOrEmpty(accountContext?.AccountId))
{
Expand Down
3 changes: 1 addition & 2 deletions examples/ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Microsoft.FeatureManagement.FeatureFilters;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Consoto.Banking.AccountService
Expand Down Expand Up @@ -59,7 +58,7 @@ public static async Task Main(string[] args)
AccountId = account
};

bool enabled = await featureManager.IsEnabledAsync(FeatureName, accountServiceContext, CancellationToken.None);
bool enabled = await featureManager.IsEnabledAsync(FeatureName, accountServiceContext);

//
// Output results
Expand Down
3 changes: 1 addition & 2 deletions examples/FeatureFlagDemo/BrowserFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Microsoft.FeatureManagement;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace FeatureFlagDemo.FeatureManagement.FeatureFilters
Expand All @@ -24,7 +23,7 @@ public BrowserFilter(IHttpContextAccessor httpContextAccessor)
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}

public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context, CancellationToken _)
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
BrowserFilterSettings settings = context.Parameters.Get<BrowserFilterSettings>() ?? new BrowserFilterSettings();

Expand Down
5 changes: 2 additions & 3 deletions examples/FeatureFlagDemo/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Microsoft.FeatureManagement;
using Microsoft.FeatureManagement.Mvc;
using System.Threading.Tasks;
using System.Threading;

namespace FeatureFlagDemo.Controllers
{
Expand All @@ -27,11 +26,11 @@ public IActionResult Index()
return View();
}

public async Task<IActionResult> About(CancellationToken cancellationToken)
public async Task<IActionResult> About()
{
ViewData["Message"] = "Your application description page.";

if (await _featureManager.IsEnabledAsync(nameof(MyFeatureFlags.CustomViewData), cancellationToken))
if (await _featureManager.IsEnabledAsync(nameof(MyFeatureFlags.CustomViewData)))
{
ViewData["Message"] = $"This is FANCY CONTENT you can see only if '{nameof(MyFeatureFlags.CustomViewData)}' is enabled.";
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;

namespace FeatureFlagDemo
Expand All @@ -24,7 +23,7 @@ public HttpContextTargetingContextAccessor(IHttpContextAccessor httpContextAcces
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}

public ValueTask<TargetingContext> GetContextAsync(CancellationToken _)
public ValueTask<TargetingContext> GetContextAsync()
{
HttpContext httpContext = _httpContextAccessor.HttpContext;

Expand Down
3 changes: 1 addition & 2 deletions examples/FeatureFlagDemo/SuperUserFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
// Licensed under the MIT license.
//
using Microsoft.FeatureManagement;
using System.Threading;
using System.Threading.Tasks;

namespace FeatureFlagDemo.FeatureManagement.FeatureFilters
{
public class SuperUserFilter : IFeatureFilter
{
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context, CancellationToken _)
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
return Task.FromResult(false);
}
Expand Down
3 changes: 1 addition & 2 deletions examples/TargetingConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Consoto.Banking.HelpDesk
Expand Down Expand Up @@ -63,7 +62,7 @@ public static async Task Main(string[] args)
Groups = user.Groups
};

bool enabled = await featureManager.IsEnabledAsync(FeatureName, targetingContext, CancellationToken.None);
bool enabled = await featureManager.IsEnabledAsync(FeatureName, targetingContext);

//
// Output results
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ public override async Task OnActionExecutionAsync(ActionExecutingContext context
//
// Enabled state is determined by either 'any' or 'all' features being enabled.
bool enabled = RequirementType == RequirementType.All ?
await Features.All(async feature => await fm.IsEnabledAsync(feature, context.HttpContext.RequestAborted).ConfigureAwait(false)).ConfigureAwait(false) :
await Features.Any(async feature => await fm.IsEnabledAsync(feature, context.HttpContext.RequestAborted).ConfigureAwait(false)).ConfigureAwait(false);
await Features.All(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false)) :
await Features.Any(async feature => await fm.IsEnabledAsync(feature).ConfigureAwait(false));

if (enabled)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionE
{
IFeatureManager featureManager = context.HttpContext.RequestServices.GetRequiredService<IFeatureManagerSnapshot>();

if (await featureManager.IsEnabledAsync(FeatureName, context.HttpContext.RequestAborted).ConfigureAwait(false))
if (await featureManager.IsEnabledAsync(FeatureName).ConfigureAwait(false))
{
IServiceProvider serviceProvider = context.HttpContext.RequestServices.GetRequiredService<IServiceProvider>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.FeatureManagement.Mvc.TagHelpers
Expand Down Expand Up @@ -56,8 +55,8 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu
IEnumerable<string> names = Name.Split(',').Select(n => n.Trim());

enabled = Requirement == RequirementType.All ?
await names.All(async n => await _featureManager.IsEnabledAsync(n, CancellationToken.None).ConfigureAwait(false)).ConfigureAwait(false) :
await names.Any(async n => await _featureManager.IsEnabledAsync(n, CancellationToken.None).ConfigureAwait(false)).ConfigureAwait(false);
await names.All(async n => await _featureManager.IsEnabledAsync(n).ConfigureAwait(false)) :
await names.Any(async n => await _featureManager.IsEnabledAsync(n).ConfigureAwait(false));
}

if (Negate)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public static IApplicationBuilder UseForFeature(this IApplicationBuilder app, st
{
IFeatureManager fm = context.RequestServices.GetRequiredService<IFeatureManagerSnapshot>();

if (await fm.IsEnabledAsync(featureName, context.RequestAborted).ConfigureAwait(false))
if (await fm.IsEnabledAsync(featureName).ConfigureAwait(false))
{
await branch(context).ConfigureAwait(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -41,7 +40,7 @@ public void Dispose()
_changeSubscription = null;
}

public Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName, CancellationToken _)
public Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)
{
if (featureName == null)
{
Expand All @@ -64,7 +63,7 @@ public Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName, Can
// The async key word is necessary for creating IAsyncEnumerable.
// The need to disable this warning occurs when implementaing async stream synchronously.
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
public async IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync([EnumeratorCancellation] CancellationToken _)
public async IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()
#pragma warning restore CS1998
{
if (Interlocked.Exchange(ref _stale, 0) != 0)
Expand Down
30 changes: 11 additions & 19 deletions src/Microsoft.FeatureManagement/ContextualFeatureFilterEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.FeatureManagement
Expand All @@ -16,7 +15,7 @@ namespace Microsoft.FeatureManagement
class ContextualFeatureFilterEvaluator : IContextualFeatureFilter<object>
{
private IFeatureFilterMetadata _filter;
private Func<object, FeatureFilterEvaluationContext, object, CancellationToken, Task<bool>> _evaluateFunc;
private Func<object, FeatureFilterEvaluationContext, object, Task<bool>> _evaluateFunc;

public ContextualFeatureFilterEvaluator(IFeatureFilterMetadata filter, Type appContextType)
{
Expand Down Expand Up @@ -44,14 +43,14 @@ public ContextualFeatureFilterEvaluator(IFeatureFilterMetadata filter, Type appC
_filter = filter;
}

public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext evaluationContext, object context, CancellationToken cancellationToken)
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext evaluationContext, object context)
{
if (_evaluateFunc == null)
{
return Task.FromResult(false);
}

return _evaluateFunc(_filter, evaluationContext, context, cancellationToken);
return _evaluateFunc(_filter, evaluationContext, context);
}

public static bool IsContextualFilter(IFeatureFilterMetadata filter, Type appContextType)
Expand All @@ -73,7 +72,7 @@ private static Type GetContextualFilterInterface(IFeatureFilterMetadata filter,
return targetInterface;
}

private static Func<object, FeatureFilterEvaluationContext, object, CancellationToken, Task<bool>> TypeAgnosticEvaluate(Type filterType, MethodInfo method)
private static Func<object, FeatureFilterEvaluationContext, object, Task<bool>> TypeAgnosticEvaluate(Type filterType, MethodInfo method)
{
//
// Get the generic version of the evaluation helper method
Expand All @@ -83,30 +82,23 @@ private static Func<object, FeatureFilterEvaluationContext, object, Cancellation
//
// Create a type specific version of the evaluation helper method
MethodInfo constructedHelper = genericHelper.MakeGenericMethod
(filterType,
method.GetParameters()[0].ParameterType,
method.GetParameters()[1].ParameterType,
method.GetParameters()[2].ParameterType,
method.ReturnType);
(filterType, method.GetParameters()[0].ParameterType, method.GetParameters()[1].ParameterType, method.ReturnType);

//
// Invoke the method to get the func
object typeAgnosticDelegate = constructedHelper.Invoke(null, new object[] { method });

return (Func<object, FeatureFilterEvaluationContext, object, CancellationToken, Task<bool>>)typeAgnosticDelegate;
return (Func<object, FeatureFilterEvaluationContext, object, Task<bool>>)typeAgnosticDelegate;
}

private static Func<object, FeatureFilterEvaluationContext, object, CancellationToken, Task<bool>> GenericTypeAgnosticEvaluate<TTarget, TParam1, TParam2, TParam3, TReturn>(MethodInfo method)
private static Func<object, FeatureFilterEvaluationContext, object, Task<bool>> GenericTypeAgnosticEvaluate<TTarget, TParam1, TParam2, TReturn>(MethodInfo method)
{
Func<TTarget, FeatureFilterEvaluationContext, TParam2, CancellationToken, Task<bool>> func =
(Func<TTarget, FeatureFilterEvaluationContext, TParam2, CancellationToken, Task<bool>>)
Delegate.CreateDelegate(typeof(Func<TTarget, FeatureFilterEvaluationContext, TParam2, CancellationToken, Task<bool>>), method);
Func<TTarget, FeatureFilterEvaluationContext, TParam2, Task<bool>> func = (Func<TTarget, FeatureFilterEvaluationContext, TParam2, Task<bool>>)Delegate.CreateDelegate
(typeof(Func<TTarget, FeatureFilterEvaluationContext, TParam2, Task<bool>>), method);

Func<object, FeatureFilterEvaluationContext, object, CancellationToken, Task<bool>> genericDelegate =
(object target, FeatureFilterEvaluationContext param1, object param2, CancellationToken param3) =>
func((TTarget)target, param1, (TParam2)param2, param3);
Func<object, FeatureFilterEvaluationContext, object, Task<bool>> genericDelegate = (object target, FeatureFilterEvaluationContext param1, object param2) => func((TTarget)target, param1, (TParam2)param2);

return genericDelegate;
}
}
}
}
5 changes: 2 additions & 3 deletions src/Microsoft.FeatureManagement/EmptySessionManager.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.FeatureManagement
Expand All @@ -11,12 +10,12 @@ namespace Microsoft.FeatureManagement
/// </summary>
class EmptySessionManager : ISessionManager
{
public Task SetAsync(string featureName, bool enabled, CancellationToken _)
public Task SetAsync(string featureName, bool enabled)
{
return Task.CompletedTask;
}

public Task<bool?> GetAsync(string featureName, CancellationToken _)
public Task<bool?> GetAsync(string featureName)
{
return Task.FromResult((bool?)null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.FeatureManagement.Utils;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.FeatureManagement.FeatureFilters
Expand All @@ -31,9 +30,8 @@ public PercentageFilter(ILoggerFactory loggerFactory)
/// Performs a percentage based evaluation to determine whether a feature is enabled.
/// </summary>
/// <param name="context">The feature evaluation context.</param>
/// <param name="cancellationToken">The cancellation token to cancel the operation.</param>
/// <returns>True if the feature is enabled, false otherwise.</returns>
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context, CancellationToken cancellationToken)
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
PercentageFilterSettings settings = context.Parameters.Get<PercentageFilterSettings>() ?? new PercentageFilterSettings();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.FeatureManagement.FeatureFilters
Expand All @@ -31,9 +30,8 @@ public TimeWindowFilter(ILoggerFactory loggerFactory)
/// Evaluates whether a feature is enabled based on a configurable time window.
/// </summary>
/// <param name="context">The feature evaluation context.</param>
/// <param name="cancellationToken">The cancellation token to cancel the operation.</param>
/// <returns>True if the feature is enabled, false otherwise.</returns>
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context, CancellationToken cancellationToken)
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
TimeWindowFilterSettings settings = context.Parameters.Get<TimeWindowFilterSettings>() ?? new TimeWindowFilterSettings();

Expand Down
Loading