Skip to content

Instantly share code, notes, and snippets.

@jmarnold
Created September 23, 2010 02:15
Show Gist options
  • Save jmarnold/592961 to your computer and use it in GitHub Desktop.
Save jmarnold/592961 to your computer and use it in GitHub Desktop.
public class ApplicationSetting
{
public string Key { get; set; }
public string Value { get; set; }
}
public class ApplicationSettingsProvider
{
private readonly IServiceLocator _locator;
private readonly IObjectResolver _resolver;
public ApplicationSettingsProvider(IServiceLocator locator, IObjectResolver resolver)
{
_locator = locator;
_resolver = resolver;
}
public T SettingsFor<T>()
where T : class, new()
{
return (T) SettingsFor(typeof (T));
}
public object SettingsFor(Type settingsType)
{
IBindingContext context = new BindingContext(_locator.GetInstance<ApplicationSettingsRequestData>(),
_locator);
BindResult result = _resolver.BindModel(settingsType, context);
result.AssertNoProblems(settingsType);
return result.Value;
}
}
public class ApplicationSettingsRequestData : IRequestData
{
private readonly ISettingsCache _settingsCache;
public ApplicationSettingsRequestData(ISettingsCache settingsCache)
{
_settingsCache = settingsCache;
}
public object Value(string key)
{
object value = null;
Value(key, v => value = v);
return value;
}
public bool Value(string key, Action<object> callback)
{
var setting = _settingsCache.Get(key);
if (setting != null)
{
callback(setting.Value);
return true;
}
return false;
}
}
public class CascadeSettingsCommand<TSettings> : BasicCommand
where TSettings : class, ISettings
{
private readonly IApplicationSettingsCache _settingsCache;
private readonly ISettingsManager _settingsManager;
private readonly ICommandContext _context;
public CascadeSettingsCommand(IApplicationSettingsCache settingsCache, ICommandContext context, ISettingsManager settingsManager)
{
_context = context;
_settingsCache = settingsCache;
_settingsManager = settingsManager;
}
protected override DoNext PerformInvoke()
{
var settings = _context.Get<TSettings>();
typeof(TSettings)
.EachProperty(p =>
{
var rawValue = p.GetValue(settings, null);
if (rawValue == null)
{
return;
}
var key = p.Name;
var value = rawValue.ToString();
if (!_settingsCache.Has(key))
{
_settingsCache.Add(key, value);
}
else
{
_settingsCache.Update(key, value);
}
});
_settingsManager.Persist(_settingsCache);
return DoNext.Continue;
}
}
public class CascadeSettingsConvention : IConfigurationAction
{
public void Configure(CommandGraph graph)
{
graph
.ChainsForExisting
.SettingsChains()
.Each(chain =>
{
graph.Observer.RecordCallStatus(chain.Placeholder(), "Adding CascadeSettingsCommand directly before placeholder");
chain
.Placeholder()
.AddBefore(new Wrapper(typeof(CascadeSettingsCommand<>).MakeGenericType(chain.EntityType)));
});
}
}
public interface IApplicationSettingsCache
{
ApplicationSetting Get(string key);
void Update(string key, string value);
void Add(string key, string value);
bool Has(string key);
}
public class MySettings : ISettings
{
public string SiteTitle { get; set; }
}
public class SampleCommandRegistry : CommandRegistry
{
public SampleCommandRegistry()
{
Applies
.ToThisAssembly()
.ToAssemblyContainingType<EntityMarker>();
Entities
.IncludedTypesInNamespaceContaining<EntityMarker>()
.IncludeTypes(t => typeof(IDomainEntity).IsAssignableFrom(t))
.IncludeTypes(t => typeof(ISettings).IsAssignableFrom(t))
.ExcludeTypes(t => t.IsEnum || t.IsInterface || t.IsAbstract);
ApplyConvention<CascadeSettingsConvention>();
}
}
public class SampleEditEndpoint
{
private readonly MySettings _settings;
private readonly ICommandInvoker _invoker;
public SampleEditEndpoint(MySettings settings, ICommandInvoker invoker)
{
_settings = settings;
_invoker = invoker;
}
public MySettings Get()
{
return _settings;
}
public InvocationResult<MySettings> Post(MySettings settings)
{
return _invoker.ForExisting<MySettings>(ctx => ctx.Set(settings));
}
}
public class SettingsRegistry : Registry
{
public SettingsRegistry()
{
IncludeRegistry<AppSettingProviderRegistry>();
Scan(x =>
{
x.AssemblyContainingType<SettingsMarker>();
x.IncludeNamespaceContainingType<SettingsMarker>();
x.Exclude(type => !typeof(ISettings).IsAssignableFrom(type));
x.Exclude(type => !type.IsClass);
x.With(new SettingsConvention());
});
}
}
public class SettingsConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
registry
.For(type)
.Use(ctx => ctx.GetInstance<ApplicationSettingsProvider>().SettingsFor(type));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment