我正在与Nop Commerce
合作,并想知道是否有人可以帮助我解决我的困惑。
我已多次调试代码,试图了解在启动Web应用程序时如何加载设置。我只是不明白!
所有设置类都实现ISettings
接口。让我们以客户设置为例..我发现它由CustomerSettings
类表示。在数据库中有一个Setting table
。客户设置的数据看起来像这样:
customersettings.usernamesenabled
customersettings.checkusernameavailabilityenabled
customersettings.allowuserstochangeusernames
... and so on...
这些设置如何以及在何处从customersettings
映射到CustomerSettings
类,以及usernamesenabled
等属性映射到CustomerSettings类中的UsernamesEnabled
属性?为什么这样实现呢?
我知道它与DependencyRegistrar
类中的以下代码有关:
builder.RegisterGeneric(typeof(ConfigurationProvider<>)).As(typeof(IConfigurationProvider<>));
builder.RegisterSource(new SettingsSource());
如果有人可以指出我正确的方向,那么我们将不胜感激。
答案 0 :(得分:7)
希望我不迟到。
要了解如何创建该结构,只需要了解一些相关要点:
-Nop.Services.Configuration.ConfigurationProvider class
-Nop.Services.Configuration.ISettingsService interface
-Nop.Services.Configuration.SettingsService class
SettingsService仅提供存储和检索存储库设置的功能,并实现一些缓存功能。
ConfigurationProvider实现了真正的魔力。
让我们看一下BuildConfiguration
方法:
// get properties we can write to
var properties = from prop in typeof(TSettings).GetProperties()
where prop.CanWrite && prop.CanRead
let setting = _settingService.GetSettingByKey<string>(typeof(TSettings).Name + "." + prop.Name)
where setting != null
where CommonHelper.GetNopCustomTypeConverter(prop.PropertyType).CanConvertFrom(typeof(string))
where CommonHelper.GetNopCustomTypeConverter(prop.PropertyType).IsValid(setting)
let value = CommonHelper.GetNopCustomTypeConverter(prop.PropertyType).ConvertFromInvariantString(setting)
select new { prop, value };
使用反射,*设置类(例如,CustomerSettings)进行检查,并使用其属性从服务加载相应的设置。
然后它将存储为字符串的值转换回来(您可以检查NopCustomTypeConverter以查看序列化是如何发生的)并将它们分配回设置实体:
properties.ToList().ForEach(p => p.prop.SetValue(Settings, p.value, null));
另一种方法,SaveSettings(TSettings设置)完全相反,采用Setting实体并将其分解,以ClassName + Propertyvalues的形式生成键 - 值对
它是这样实现的,因为它部署了IoC,segregation of interfaces,n-tier和其他模式的概念,以确保可维护性(基于API的组件化,可测试性ecc)。