Skip to content

Commit

Permalink
introduce Feature.Name and Feature.NamingConvention
Browse files Browse the repository at this point in the history
  • Loading branch information
mexx committed Nov 27, 2012
1 parent d610e9e commit cdc1b13
Show file tree
Hide file tree
Showing 22 changed files with 163 additions and 109 deletions.
2 changes: 1 addition & 1 deletion Source/FeatureSwitcher.Configuration/AppConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private FeaturesSection FeaturesSection
get { return _features ?? SectionGroup.GetFeaturesSection(_settings.SectionGroupName, _settings.IgnoreConfigurationErrors); }
}

public bool? IsEnabled(string feature)
public bool? IsEnabled(Feature.Name feature)
{
return Features(feature).GetValueOrDefault(Default(feature).GetValueOrDefault());
}
Expand Down
2 changes: 1 addition & 1 deletion Source/FeatureSwitcher.Configuration/AppConfigDefault.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public AppConfigDefault(DefaultSection defaultSection)
_defaultSection = defaultSection;
}

public bool? IsEnabled(string feature)
public bool? IsEnabled(Feature.Name feature)
{
if (_defaultSection == null)
return null;
Expand Down
4 changes: 2 additions & 2 deletions Source/FeatureSwitcher.Configuration/AppConfigFeatures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ public AppConfigFeatures(FeaturesSection features)
_features = features;
}

public bool? IsEnabled(string feature)
public bool? IsEnabled(Feature.Name feature)
{
if (_features == null)
return null;

var featureElement = _features.Features[feature];
var featureElement = _features.Features[feature.Value];

if (featureElement == null)
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ namespace FeatureSwitcher.Configuration
internal class FeatureConfigurationFor<TContext> : IConfigureFeaturesFor<TContext>, IConfigureBehaviorFor<TContext>, IConfigureNamingFor<TContext>
where TContext : IContext
{
private Func<TContext, Feature.NameOf[]> _nameOf;
private Func<TContext, Feature.NameOf[]> NameOf
private Func<TContext, Feature.NamingConvention[]> _namingConvention;
private Func<TContext, Feature.NamingConvention[]> NamingConvention
{
get { return _nameOf ?? (ctx => null); }
get { return _namingConvention ?? (ctx => null); }
}
private Func<TContext, Feature.Behavior[]> _behavior;
private Func<TContext, Feature.Behavior[]> Behavior
Expand Down Expand Up @@ -38,19 +38,19 @@ IConfigureFeaturesFor<TContext> IConfigureFeaturesFor<TContext>.And
get { return this; }
}

public IConfigureNaming NamedBy
IConfigureNaming IConfigureFeatures.NamedBy
{
get { return this; }
}

public IConfigureBehavior ConfiguredBy
IConfigureBehavior IConfigureFeatures.ConfiguredBy
{
get { return this; }
}

IConfigureFeaturesFor<TContext> IConfigureNamingFor<TContext>.Custom(Func<TContext, Feature.NameOf[]> naming)
IConfigureFeaturesFor<TContext> IConfigureNamingFor<TContext>.Custom(Func<TContext, Feature.NamingConvention[]> namingConventions)
{
_nameOf = naming;
_namingConvention = namingConventions;
return this;
}

Expand All @@ -60,9 +60,9 @@ IConfigureFeaturesFor<TContext> IConfigureBehaviorFor<TContext>.Custom(Func<TCon
return this;
}

IConfigureFeatures IConfigureNaming.Custom(params Feature.NameOf[] nameOfs)
IConfigureFeatures IConfigureNaming.Custom(params Feature.NamingConvention[] namingConventions)
{
return (this as IConfigureNamingFor<TContext>).Custom(ctx => nameOfs);
return (this as IConfigureNamingFor<TContext>).Custom(ctx => namingConventions);
}

IConfigureFeatures IConfigureBehavior.Custom(params Feature.Behavior[] behaviors)
Expand All @@ -73,7 +73,7 @@ IConfigureFeatures IConfigureBehavior.Custom(params Feature.Behavior[] behaviors
public Feature.Configuration For(TContext context)
{
return new Feature.Configuration(
type => (NameOf(context) ?? new Feature.NameOf[0]).Where(x => x != null).Select(x => x(type)).FirstOrDefault(x => x != null),
type => (NamingConvention(context) ?? new Feature.NamingConvention[0]).Where(x => x != null).Select(x => x(type)).FirstOrDefault(x => x != null),
name => (Behavior(context) ?? new Feature.Behavior[0]).Select(x => x(name)).FirstOrDefault(x => x.HasValue),
typeof(TContext) != typeof(Default) ? FeatureConfiguration.For(Default.Context) : Feature.Configuration.Current);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public interface IConfigureNamingFor<out TContext> : IConfigureNaming
/// </summary>
/// <param name="namingConventions">The naming conventions to use.</param>
/// <returns>the extension point for features configuration in contexts of type <typeparamref name="TContext"/>.</returns>
IConfigureFeaturesFor<TContext> Custom(Func<TContext, Feature.NameOf[]> namingConventions);
IConfigureFeaturesFor<TContext> Custom(Func<TContext, Feature.NamingConvention[]> namingConventions);
}
}
16 changes: 3 additions & 13 deletions Source/FeatureSwitcher.Specs/Domain/EnableByName.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
using System;
using FeatureSwitcher.Configuration;

namespace FeatureSwitcher.Specs.Domain
{
public class EnableByName<T>
public static class EnableByName<T>
where T : IFeature
{
public readonly static EnableByName<T> Instance = new EnableByName<T>();

public bool? IsEnabled(string feature)
public static bool? IsEnabled(Feature.Name name)
{
return Features.OfType<T>.EnabledByTypeName(feature);
}

public string For(Type featureType)
{
return Features.OfType<T>.NamedByTypeName(featureType);
return typeof(T).Name == name.Value ? true : (bool?)null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,25 @@ public class When_behavior_is_not_configured_in_context_and_configured_general :
{
Features.Are.
ConfiguredBy.Custom(
EnableByName<Basic>.Instance.IsEnabled,
EnableByName<Simple>.Instance.IsEnabled,
EnableByName<Complex>.Instance.IsEnabled).And.
EnableByName<Basic>.IsEnabled,
EnableByName<Simple>.IsEnabled,
EnableByName<Complex>.IsEnabled).And.
NamedBy.TypeName();

In<BusinessBranch>.Contexts.FeaturesAre().
NamedBy.TypeFullName();
};

Behaves_like<Enabled<Basic>> a_disabled_basic_feature;
Behaves_like<EnabledInDefault<Basic>> a_disabled_basic_feature_in_default;
Behaves_like<Enabled<Basic>> an_enabled_basic_feature;
Behaves_like<EnabledInDefault<Basic>> an_enabled_basic_feature_in_default;
Behaves_like<DisabledInHeadquaters<Basic>> a_disabled_basic_feature_in_headquarters;

Behaves_like<Enabled<Simple>> a_disabled_simple_feature;
Behaves_like<EnabledInDefault<Simple>> a_disabled_simple_feature_in_default;
Behaves_like<Enabled<Simple>> an_enabled_simple_feature;
Behaves_like<EnabledInDefault<Simple>> an_enabled_simple_feature_in_default;
Behaves_like<DisabledInHeadquaters<Simple>> an_enabled_feature_in_headquarters;

Behaves_like<Enabled<Complex>> a_disabled_complex_feature;
Behaves_like<EnabledInDefault<Complex>> a_disabled_complex_feature_in_default;
Behaves_like<Enabled<Complex>> an_enabled_complex_feature;
Behaves_like<EnabledInDefault<Complex>> an_enabled_complex_feature_in_default;
Behaves_like<DisabledInHeadquaters<Complex>> a_disabled_complex_feature_in_headquarters;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ public class When_chaining_application_configuration_and_partial_configurations
Features.Are
.ConfiguredBy.Custom(
new AppConfig(true).Features,
EnableByName<Simple>.Instance.IsEnabled,
EnableByName<Simple>.IsEnabled,
new AppConfig(true).Default).And
.NamedBy.Custom(
EnableByName<Simple>.Instance.For,
Features.OfAnyType.NamedByTypeFullName);
Features.OfType<Simple>.NamedByTypeName,
Features.OfType<Complex>.NamedByTypeFullName);

Behaves_like<Disabled<Basic>> a_disabled_basic_feature;
Behaves_like<DisabledInDefault<Basic>> a_disabled_basic_feature_in_default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace FeatureSwitcher.Specs
public class When_chaining_multiple_partial_configurations : WithCleanUp
{
Establish ctx = () => Features.Are.
ConfiguredBy.Custom(EnableByName<Simple>.Instance.IsEnabled, EnableByName<Complex>.Instance.IsEnabled).And.
NamedBy.Custom(EnableByName<Simple>.Instance.For, EnableByName<Complex>.Instance.For);
ConfiguredBy.Custom(EnableByName<Simple>.IsEnabled, EnableByName<Complex>.IsEnabled).And.
NamedBy.Custom(Features.OfType<Simple>.NamedByTypeName, Features.OfType<Complex>.NamedByTypeName);

Behaves_like<Disabled<Basic>> a_disabled_basic_feature;
Behaves_like<DisabledInDefault<Basic>> a_disabled_basic_feature_in_default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ public class When_chaining_multiple_partial_configurations_and_contexts : WithCl
Establish ctx = () =>
{
Features.Are
.ConfiguredBy.Custom(EnableByName<Simple>.Instance.IsEnabled, EnableByName<Complex>.Instance.IsEnabled).And
.NamedBy.Custom(EnableByName<Simple>.Instance.For, EnableByName<Complex>.Instance.For);
.ConfiguredBy.Custom(EnableByName<Simple>.IsEnabled, EnableByName<Complex>.IsEnabled).And
.NamedBy.Custom(Features.OfType<Simple>.NamedByTypeName, Features.OfType<Complex>.NamedByTypeName);

In<Default>.Contexts.FeaturesAre()
.AlwaysDisabled().And
.ConfiguredBy.Custom(Features.OfType<Simple>.Disabled, Features.OfType<Basic>.Disabled, Features.OfAnyType.Enabled).And
.NamedBy.TypeFullName();

In<BusinessBranch>.Contexts.FeaturesAre()
.ConfiguredBy.Custom(EnableByName<Basic>.Instance.IsEnabled).And
.NamedBy.Custom(EnableByName<Basic>.Instance.For);
.ConfiguredBy.Custom(EnableByName<Basic>.IsEnabled).And
.NamedBy.Custom(Features.OfType<Basic>.NamedByTypeName);
};

Behaves_like<Enabled<Simple>> an_enabled_feature_simple;
Expand All @@ -34,7 +34,7 @@ public class When_chaining_multiple_partial_configurations_and_contexts : WithCl
Behaves_like<EnabledInHeadquaters<Basic>> an_enabled_feature_basic_in_headquarters;

Behaves_like<Enabled<Complex>> an_enabled_feature_complex;
Behaves_like<DisabledInDefault<Complex>> a_disabled_feature_complex_in_default;
Behaves_like<DisabledInHeadquaters<Complex>> a_disabled_feature_complex_in_headquarters;
Behaves_like<EnabledInDefault<Complex>> an_enabled_feature_complex_in_default;
Behaves_like<EnabledInHeadquaters<Complex>> an_enabled_feature_complex_in_headquarters;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class When_naming_is_not_configured_in_context_and_configured_general : W
Features.Are.NamedBy.TypeName();

In<BusinessBranch>.Contexts.FeaturesAre().
ConfiguredBy.Custom(EnableByName<Simple>.Instance.IsEnabled);
ConfiguredBy.Custom(Features.OfType<Simple>.Enabled);
};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace FeatureSwitcher.Specs
public class When_using_partial_configuration : WithCleanUp
{
Establish ctx = () => Features.Are.
ConfiguredBy.Custom(EnableByName<Simple>.Instance.IsEnabled).And.
NamedBy.Custom(EnableByName<Simple>.Instance.For);
ConfiguredBy.Custom(EnableByName<Simple>.IsEnabled).And.
NamedBy.Custom(Features.OfType<Simple>.NamedByTypeName);

Behaves_like<Disabled<Basic>> a_disabled_basic_feature;
Behaves_like<DisabledInDefault<Basic>> a_disabled_basic_feature_in_default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ public class When_using_partial_configuration_and_contexts : WithCleanUp
Establish ctx = () =>
{
Features.Are.
ConfiguredBy.Custom(EnableByName<Simple>.Instance.IsEnabled).And.
NamedBy.Custom(EnableByName<Simple>.Instance.For);
ConfiguredBy.Custom(EnableByName<Simple>.IsEnabled).And.
NamedBy.Custom(Features.OfType<Simple>.NamedByTypeName);

In<Default>.Contexts.FeaturesAre().
ConfiguredBy.Custom(EnableByName<Basic>.Instance.IsEnabled).And.
NamedBy.Custom(EnableByName<Basic>.Instance.For);
ConfiguredBy.Custom(EnableByName<Basic>.IsEnabled).And.
NamedBy.Custom(Features.OfType<Basic>.NamedByTypeName);

In<BusinessBranch>.Contexts.FeaturesAre().
ConfiguredBy.Custom(EnableByName<Complex>.Instance.IsEnabled).And.
NamedBy.Custom(EnableByName<Complex>.Instance.For);
ConfiguredBy.Custom(EnableByName<Complex>.IsEnabled).And.
NamedBy.Custom(Features.OfType<Complex>.NamedByTypeName);
};

Behaves_like<Disabled<Basic>> a_disabled_feature_basic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ namespace FeatureSwitcher.Configuration
public static partial class Features
{
/// <summary>
/// Builder for features configuration.
/// Builder for feature configuration.
/// </summary>
public class ConfigurationBuilder : IConfigureFeatures, IConfigureNaming, IConfigureBehavior
private class ConfigurationBuilder : IConfigureFeatures, IConfigureNaming, IConfigureBehavior
{
private readonly Feature.Configuration _fallback;
private Feature.NameOf _namingConvention;
private Feature.NamingConvention _namingConvention;
private Feature.Behavior _behavior;

/// <summary>
Expand Down Expand Up @@ -46,7 +46,7 @@ IConfigureBehavior IConfigureFeatures.ConfiguredBy
get { return this; }
}

IConfigureFeatures IConfigureNaming.Custom(params Feature.NameOf[] namingConventions)
IConfigureFeatures IConfigureNaming.Custom(params Feature.NamingConvention[] namingConventions)
{
_namingConvention = null;
if (namingConventions != null)
Expand Down
47 changes: 33 additions & 14 deletions Source/FeatureSwitcher/Configuration/Features.OfAnyType.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;

namespace FeatureSwitcher.Configuration
{
public static partial class Features
Expand All @@ -8,28 +10,45 @@ public static partial class Features
public static class OfAnyType
{
/// <summary>
/// Gets the behavior which enables any feature.
/// Enables any feature.
/// </summary>
public static Feature.Behavior Enabled { get; private set; }
/// <param name="featureName">The name of the feature.</param>
/// <returns>always <c>true</c>.</returns>
public static bool? Enabled(Feature.Name featureName)
{
return true;
}

/// <summary>
/// Gets the behavior which disables any feature.
/// Disables any feature.
/// </summary>
public static Feature.Behavior Disabled { get; private set; }
/// <param name="featureName">The name of the feature.</param>
/// <returns>always <c>false</c>.</returns>
public static bool? Disabled(Feature.Name featureName)
{
return false;
}

/// <summary>
/// Gets the naming convention which names any feature by name of the type.
/// Provides the name of the feature.
/// The value of the name is the name of <paramref name="featureType"/>.
/// </summary>
public static Feature.NameOf NamedByTypeName { get; private set; }
/// <param name="featureType">The type of the feature.</param>
/// <returns>the name of the feature.</returns>
public static Feature.Name NamedByTypeName(Type featureType)
{
return new Feature.Name(featureType, featureType.Name);
}

/// <summary>
/// Gets the naming convention which names any feature by full name of the type.
/// Provides the name of the feature.
/// The value of the name is the full name of <paramref name="featureType"/>.
/// </summary>
public static Feature.NameOf NamedByTypeFullName { get; private set; }

static OfAnyType()
/// <param name="featureType">The type of the feature.</param>
/// <returns>the name of the feature.</returns>
public static Feature.Name NamedByTypeFullName(Type featureType)
{
Enabled = name => true;
Disabled = name => false;
NamedByTypeName = type => type.Name;
NamedByTypeFullName = type => type.FullName;
return new Feature.Name(featureType, featureType.FullName);
}
}
}
Expand Down
Loading

0 comments on commit cdc1b13

Please sign in to comment.