-
Notifications
You must be signed in to change notification settings - Fork 119
Allow different type of filters to share the same Alias #262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
15d6a07
eb412f4
745ea3e
b5a10f6
8483c5e
c4192a5
6082e9f
b0bd5df
f57bd7f
d39de05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -25,8 +25,8 @@ class FeatureManager : IFeatureManager, IDisposable | |||||
| private readonly IEnumerable<IFeatureFilterMetadata> _featureFilters; | ||||||
| private readonly IEnumerable<ISessionManager> _sessionManagers; | ||||||
| private readonly ILogger _logger; | ||||||
| private readonly ConcurrentDictionary<string, IFeatureFilterMetadata> _filterMetadataCache; | ||||||
| private readonly ConcurrentDictionary<string, ContextualFeatureFilterEvaluator> _contextualFeatureFilterCache; | ||||||
| private readonly ConcurrentDictionary<ValueTuple<string, Type>, IFeatureFilterMetadata> _filterMetadataCache; | ||||||
| private readonly ConcurrentDictionary<ValueTuple<string, Type>, ContextualFeatureFilterEvaluator> _contextualFeatureFilterCache; | ||||||
| private readonly FeatureManagementOptions _options; | ||||||
| private readonly IMemoryCache _parametersCache; | ||||||
|
|
||||||
|
|
@@ -48,8 +48,8 @@ public FeatureManager( | |||||
| _featureFilters = featureFilters ?? throw new ArgumentNullException(nameof(featureFilters)); | ||||||
| _sessionManagers = sessionManagers ?? throw new ArgumentNullException(nameof(sessionManagers)); | ||||||
| _logger = loggerFactory.CreateLogger<FeatureManager>(); | ||||||
| _filterMetadataCache = new ConcurrentDictionary<string, IFeatureFilterMetadata>(); | ||||||
| _contextualFeatureFilterCache = new ConcurrentDictionary<string, ContextualFeatureFilterEvaluator>(); | ||||||
| _filterMetadataCache = new ConcurrentDictionary<ValueTuple<string, Type>, IFeatureFilterMetadata>(); | ||||||
| _contextualFeatureFilterCache = new ConcurrentDictionary<ValueTuple<string, Type>, ContextualFeatureFilterEvaluator>(); | ||||||
| _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); | ||||||
| _parametersCache = new MemoryCache(new MemoryCacheOptions()); | ||||||
| } | ||||||
|
|
@@ -141,7 +141,17 @@ private async Task<bool> IsEnabledAsync<TContext>(string feature, TContext appCo | |||||
| continue; | ||||||
| } | ||||||
|
|
||||||
| IFeatureFilterMetadata filter = GetFeatureFilterMetadata(featureFilterConfiguration.Name); | ||||||
| IFeatureFilterMetadata filter; | ||||||
|
|
||||||
| if (useAppContext) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're now saying a call to Just use contextual filter if its defined for the context, otherwise use the no contextual filter.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Context may be null. I think we still need to distinguish the case that users intend to pass null as the context. |
||||||
| { | ||||||
| filter = GetFeatureFilterMetadata(featureFilterConfiguration.Name, typeof(TContext)) ?? | ||||||
| GetFeatureFilterMetadata(featureFilterConfiguration.Name, null); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| filter = GetFeatureFilterMetadata(featureFilterConfiguration.Name, null); | ||||||
| } | ||||||
|
|
||||||
| if (filter == null) | ||||||
| { | ||||||
|
|
@@ -165,7 +175,7 @@ private async Task<bool> IsEnabledAsync<TContext>(string feature, TContext appCo | |||||
|
|
||||||
| // | ||||||
| // IContextualFeatureFilter | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
At this point we should already know whether the filter is a contextual filter or not by whether filter was populated with or without an app context. |
||||||
| if (useAppContext) | ||||||
| if (useAppContext && ContextualFeatureFilterEvaluator.IsContextualFilter(filter, typeof(TContext))) | ||||||
|
||||||
| { | ||||||
| ContextualFeatureFilterEvaluator contextualFilter = GetContextualFeatureFilter(featureFilterConfiguration.Name, typeof(TContext)); | ||||||
|
|
||||||
|
|
@@ -267,48 +277,72 @@ private void BindSettings(IFeatureFilterMetadata filter, FeatureFilterEvaluation | |||||
| context.Settings = settings; | ||||||
| } | ||||||
|
|
||||||
| private IFeatureFilterMetadata GetFeatureFilterMetadata(string filterName) | ||||||
| private bool IsFilterNameMatched(Type filterType, string filterName) | ||||||
|
||||||
| private bool IsFilterNameMatched(Type filterType, string filterName) | |
| private bool IsMatchingName(Type filterType, string filterName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see an update to the name
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, what if there is a filter MyProduct.MyFilter as well as MyOrg.MyProduct.MyFilter? We treat them as distinct names?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. If the configuration of a feature flag contains any filters with a namespace, the feature manager will try to find a registered filter whose alias is the same as the filter name in the feature flag configuration.
zhiyuanliang-ms marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
zhiyuanliang-ms marked this conversation as resolved.
Show resolved
Hide resolved
zhiyuanliang-ms marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
zhiyuanliang-ms marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT license. | ||
| // | ||
| using Microsoft.FeatureManagement; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Tests.FeatureManagement | ||
| { | ||
| interface IDummyContext | ||
| { | ||
| string DummyProperty { get; set; } | ||
| } | ||
|
|
||
| class DummyContext : IDummyContext | ||
| { | ||
| public string DummyProperty { get; set; } | ||
| } | ||
|
|
||
| [FilterAlias(Alias)] | ||
| class DuplicatedAliasFeatureFilter1 : IFeatureFilter | ||
| { | ||
| private const string Alias = "DuplicatedFilterName"; | ||
|
|
||
| public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context) | ||
| { | ||
| return Task.FromResult(true); | ||
| } | ||
| } | ||
|
|
||
| [FilterAlias(Alias)] | ||
| class DuplicatedAliasFeatureFilter2 : IFeatureFilter | ||
| { | ||
| private const string Alias = "DuplicatedFilterName"; | ||
|
|
||
| public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context) | ||
| { | ||
| return Task.FromResult(true); | ||
| } | ||
| } | ||
|
|
||
| [FilterAlias(Alias)] | ||
| class ContextualDuplicatedAliasFeatureFilterWithAccountContext : IContextualFeatureFilter<IAccountContext> | ||
| { | ||
| private const string Alias = "DuplicatedFilterName"; | ||
|
|
||
| public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context, IAccountContext accountContext) | ||
| { | ||
| return Task.FromResult(true); | ||
| } | ||
| } | ||
|
|
||
| [FilterAlias(Alias)] | ||
| class ContextualDuplicatedAliasFeatureFilterWithDummyContext1 : IContextualFeatureFilter<IDummyContext> | ||
| { | ||
| private const string Alias = "DuplicatedFilterName"; | ||
|
|
||
| public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context, IDummyContext dummyContext) | ||
| { | ||
| return Task.FromResult(true); | ||
| } | ||
| } | ||
|
|
||
| [FilterAlias(Alias)] | ||
| class ContextualDuplicatedAliasFeatureFilterWithDummyContext2 : IContextualFeatureFilter<IDummyContext> | ||
| { | ||
| private const string Alias = "DuplicatedFilterName"; | ||
|
|
||
| public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context, IDummyContext dummyContext) | ||
| { | ||
| return Task.FromResult(true); | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.