I'm looking for a good way to incorporate settings inside my webapp (asp mvc). I've came across a really nice implementation in NopCommerce. NopCommerce stores the values in a database table, with a name and value. The name is derived from the class and property name (e.g. customersettings.settingname1)
The exact way NopCommerce works with settings can be found in this question: Understanding how Nop Commerce settings are loaded from the database
NopCommerce uses Autofac as DI framework to bind the Settings
to the ConfigurationProvider
as follows (as I'm correct).
return RegistrationBuilder
.ForDelegate((c, p) => c.Resolve<IConfigurationProvider<TSettings>>().Settings)
.InstancePerHttpRequest()
.CreateRegistration();
In the appropriate classes, you can now use ClientSettings
as a parameter, and it's automatically filled with data from the database.
I really like this implementation, because it is very flexible. The problem however is that I'm using Ninject. I've tried several things to get the correct bindings, but can't seem to find the correct implementation. Does anyone have an idea how to get this working?
EDIT:
I found a way to bind ClientSettings
directly:
kernel.Bind<ClientSettings>()
.ToMethod(ctx => ctx.Kernel.Get<IConfigurationProvider<ClientSettings>>().Settings)
.InRequestScope();
But is there a way to achieve this?
kernel.Bind<ISettings>()
.ToMethod(ctx => ctx.Kernel.Get<IConfigurationProvider<ISettings>>().Settings)
.InRequestScope();
EDIT 2
I think I'm getting close, but still run into some problems. I create a custom Binding Generator:
public class SettingsBindGenerator : IBindingGenerator
{
static readonly MethodInfo BuildMethod = typeof(SettingsBindGenerator).GetMethod(
"BuildRegistration",
BindingFlags.Static | BindingFlags.NonPublic);
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
var obj = typeof (object).IsAssignableFrom(type);
if (type != null && typeof(ISettings).IsAssignableFrom(type))
{
var buildMethod = BuildMethod.MakeGenericMethod(type);
var methodResult = buildMethod.Invoke(null, new object[]{bindingRoot});
var castedResult = methodResult as IBindingWhenInNamedWithOrOnSyntax<object>;
yield return castedResult;
}
}
static IBindingWhenInNamedWithOrOnSyntax<TSettings> BuildRegistration<TSettings>(IBindingRoot bindingRoot) where TSettings : ISettings, new()
{
return bindingRoot.Bind<TSettings>().ToMethod(
ctx => ctx.Kernel.Get<IConfigurationProvider<TSettings>>().Settings);
}
}
This works for 99%. However, for some reason, buildMethod.Invoke returns an BindingConfigurationBuilder, and not an IBindingWhenInNamedWithOrOnSyntax. Therefor, castedResult is always NULL. Anybody got an idea how to correct this?
LAST EDIT
I don't know why, but suddenly it works! Glad I've finally figured it out. Thanx Remo!