-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Features should be configurable within other features (#10)
* Stuff * Cleanup And Tests * Make Extension and Rename TConfig to TOptions
- Loading branch information
Showing
8 changed files
with
219 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
src/Featurize/ConfigFeatures/ConfigureFeatureWithOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Featurize.ConfigFeatures; | ||
|
||
internal static class ConfigureFeatureWithOptions | ||
{ | ||
private static Type[] GetConfigInterfaces(IFeature feature) | ||
{ | ||
return feature.GetType().GetInterfaces().Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IConfigureFeature<,>)).ToArray(); | ||
} | ||
|
||
internal static IFeatureCollection Configure(this IFeatureCollection features) | ||
{ | ||
var results = features.Where(x => GetConfigInterfaces(x).Any()) | ||
.SelectMany(x => { | ||
var interfaces = GetConfigInterfaces(x); | ||
var list = new List<IFeatureWithOptions>(); | ||
foreach (var i in interfaces) | ||
{ | ||
var con = Activator.CreateInstance(typeof(FeatureWithOptionsRunner<,>).MakeGenericType(i.GetGenericArguments()), x); | ||
if (con is IFeatureWithOptions r) | ||
list.Add(r); | ||
} | ||
return list.ToArray(); | ||
}) | ||
.ToArray(); | ||
|
||
foreach (var item in results) | ||
{ | ||
item.ConfigureFeature(features); | ||
} | ||
|
||
return features; | ||
} | ||
|
||
internal static IFeature[] GetConfigurableFeatures(FeatureCollection features) | ||
{ | ||
return features | ||
.Where(x => { | ||
var interfaces = x.GetType().GetInterfaces() | ||
.Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IConfigureFeature<,>)); | ||
return interfaces.Any(); | ||
}).ToArray(); | ||
} | ||
} | ||
|
||
internal interface IFeatureWithOptions | ||
{ | ||
void ConfigureFeature(IFeatureCollection features); | ||
} | ||
|
||
internal class FeatureWithOptionsRunner<TFeature, TOption> : IFeatureWithOptions | ||
where TFeature : IFeatureWithConfigurableOptions<TOption> | ||
where TOption : class | ||
{ | ||
private readonly IConfigureFeature<TFeature, TOption> _configFeature; | ||
|
||
public FeatureWithOptionsRunner(IConfigureFeature<TFeature, TOption> configFeature) | ||
{ | ||
_configFeature = configFeature; | ||
} | ||
|
||
public void ConfigureFeature(IFeatureCollection features) | ||
{ | ||
var feature = features.OfType<IFeatureWithConfigurableOptions<TOption>>().FirstOrDefault(); | ||
if(feature != null) | ||
{ | ||
_configFeature.Configure(feature.Options); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace Featurize; | ||
|
||
/// <summary> | ||
/// Marks a Feature to Configure another feature. | ||
/// </summary> | ||
/// <typeparam name="TFeature"></typeparam> | ||
/// <typeparam name="TOptions"></typeparam> | ||
public interface IConfigureFeature<TFeature, TOptions> : IFeature | ||
where TFeature : IFeatureWithConfigurableOptions<TOptions> | ||
{ | ||
/// <summary> | ||
/// Method called to configure Dependent Feature. | ||
/// </summary> | ||
/// <param name="options"></param> | ||
void Configure(TOptions options); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
namespace Featurize.Tests; | ||
public partial class Get | ||
{ | ||
[Test] | ||
public void Should_configure_options() | ||
{ | ||
var features = new FeatureCollection(); | ||
|
||
features.AddWithOptions<FeatureWithConfigurableOptions, FeatureOptions>( x=> | ||
{ | ||
x.Items.Add("First"); | ||
}); | ||
features.Add(new ConfigureOptionsFeature()); | ||
features.Add(new ConfigureOptionsFeature1()); | ||
|
||
var feature = features.Get<FeatureWithConfigurableOptions>(); | ||
|
||
feature.Should().NotBeNull(); | ||
feature!.Options.Items.Should().HaveCount(3); | ||
|
||
} | ||
} | ||
|
||
public partial class GetEnumerator | ||
{ | ||
|
||
[Test] | ||
public void Should_Configure_Options() | ||
{ | ||
var features = new FeatureCollection(); | ||
var feature = FeatureWithConfigurableOptions.Create(new FeatureOptions()); | ||
var config = new ConfigureOptionsFeature(); | ||
|
||
features.Add(feature); | ||
features.Add(config); | ||
//features.Add(new ConfigureOptionsFeature1()); | ||
|
||
_ = features.GetEnumerator(); | ||
_ = features.GetEnumerator(); | ||
|
||
config.IsCalled.Should().BeTrue(); | ||
feature.Options.Items.Should().HaveCount(1); | ||
} | ||
} | ||
|
||
|
||
|
||
public class ConfigureOptionsFeature : IConfigureFeature<FeatureWithConfigurableOptions, FeatureOptions> | ||
{ | ||
public bool IsCalled = false; | ||
public void Configure(FeatureOptions options) | ||
{ | ||
IsCalled= true; | ||
options.Items.Add(GetType().Name); | ||
} | ||
} | ||
|
||
public class ConfigureOptionsFeature1 : IConfigureFeature<FeatureWithConfigurableOptions, FeatureOptions> | ||
{ | ||
public bool IsCalled = false; | ||
public void Configure(FeatureOptions options) | ||
{ | ||
IsCalled = true; | ||
options.Items.Add(GetType().Name); | ||
} | ||
} | ||
|
||
public class FeatureOptions | ||
{ | ||
public HashSet<string> Items { get; set; } = new(); | ||
} | ||
|
||
public class FeatureWithConfigurableOptions : | ||
IFeatureWithConfigurableOptions<FeatureOptions>, | ||
IFeatureWithOptions<FeatureWithConfigurableOptions, FeatureOptions> | ||
|
||
{ | ||
public FeatureOptions Options { get; private set; } | ||
|
||
public static FeatureWithConfigurableOptions Create(FeatureOptions config) | ||
{ | ||
return new FeatureWithConfigurableOptions() { | ||
Options = config | ||
}; | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters