设置管理
介绍
每个应用都需要存储设置,并且在应用的某些地方需要使用这些设置。ABP提供了一个强大的在服务端和客户端都可以使用的基础设施存储/获取应用、租户和用户级别的设置。
一个设置是一个名称-值字符串对,一般存放在数据库(或其他源)。我们可以存储非字符串值,但需要把他们转换成字符串。
关于 ISettingStore
为了使用设置系统,ISettingStore接口必须实现。虽然可以用自己的方式实现,但是module-zero工程已经完整的实现了它。如果没有实现的话,将会从应用的配置文件(web.config或app.config)读取配置,但是不能改变任何设置。设置范围也不会起作用。
定义设置
设置在使用前必须先定义。ABP设计为模块的。所以,不同的模块有不同的设置。模块应该创建一个集成子SettingProvider的类,以便定义设置。设置提供者的示例如下:
public class MySettingProvider : SettingProvider
{
public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context)
{
return new[]
{
new SettingDefinition(
"SmtpServerAddress",
"127.0.0.1"
), new SettingDefinition(
"PassiveUsersCanNotLogin",
"true",
scopes: SettingScopes.Application | SettingScopes.Tenant
), new SettingDefinition(
"SiteColorPreference",
"red",
scopes: SettingScopes.User,
isVisibleToClients: true
) };
}
}
GetSettingDefinitions方法返回SettingDefinition对象。SettingDefinition类的构造函数里有一些参数:
- Name(需要):一个设置必须有一个系统范围的唯一名称。建议为设置名称定义一个常量字符串而不是魔力字符串。
- Default Value:设置应该有默认值。默认值可以为null或空字符串。
- Scopes:设置应该有范围(参见下面部分)。
- Display Name:本地化的字符串,可以用来在UI中显示的设置名称。
- Description:本地化的字符串,可以用来在UI中显示设置的描述信息。
- Group:用来进行组设置。仅对UI使用,在设置管理中没有用。
- IsVisibleToClients:设置为true可以使设置在客户端可用。
- IsInherited:用来决定设置是否通过租户或用户继承的(参见设置范围部分)。
- CustomData:用来设置自定义数据。
创建一个设置提供者之后,我们应该在模块的PreInitialize方法中注册:
Configuration.Settings.Providers.Add<MySettingProvider>();
设置提供者自动注册到依赖注入系统。所以,设置提供者可以注入任何依赖项(比如仓储),使用其他资源来建造设置定义。
设置范围
有三种设置范围(或级别),定义在SettingScopes枚举里:
- Application:应用级别用来设置用户/租户无关的设置。例如,我们可以顶一个名为“SmtpServerAddress”的设置,当发送电邮的时候来获取服务器IP地址。如果这个设置只有一个值(不随用户改变),那么这个设置可以定义为应用级别。
- Tenant:如果应用是多租户的,我们可以定义特定租户的设置。
- User:我们可以使用用户范围的设置来存储/获取每一个特定用户的设置值。
SettingScopes枚举有Flags特性,所以我们可以定义多余一种级别的设置。
设置范围默认是分级的(除非设置isInherited为false)。例如,如果我们定义了一个设置的范围为“Application | Tenant | User”并且尝试获取这个设置的当前值:
- 如果它定义(重写)为用户级别的,将得到特定用户的值。
- 如果不是,将得到特定租户的值,如果它定义(重写)为租户级别的。
- 如果不是,将得到应用值,如果定义了的话。
- 如果不是,将得到默认值。
默认值可以为null或空字符串。建议尽可能为设置提供默认值。
重写设置定义
context.Manager可以用来获取设置定义并可改变设置值。使用这种方式,可以用来操作依赖模块的设置定义。
获取设置值
定义一个设置之后,我们可以在服务端和客户端获取设置的当前值。
服务端
ISettingManager用来执行设置操作。我们可以在应用的任何地方注入并使用它。ISettingManager定义了许多方法获取设置值。
使用最多的方法是GetSettingValue(或者GetSettingValueAsync用来异步调用)。它返回设置的当前值,基于默认值、应用、租户和用户设置(如在先前设置范围部分描述的)。例如:
//Getting a boolean value (async call)
var value1 = await SettingManager.GetSettingValueAsync<bool>("PassiveUsersCanNotLogin"); //Getting a string value (sync call)
var value2 = SettingManager.GetSettingValue("SmtpServerAddress");
GetSettingValue有泛型和异步版本,如上所示。也有方法可以获取特定租户或用户设置值、所有设置值的列表。
因为ISettingManager被广泛使用,一些特定的基类(如ApplicationService,DomainService和AbpController)有一个名为SettingManager的属性。如果我们派生自这些类,就不需要显示的注入了。
客户端
如果当定义设置时,将IsVisileToClients置为true,就可以在客户端使用javascript获取它的当前值。abp.setting命名空间定义了需要的函数和对象。例如:
var currentColor = abp.setting.get("SiteColorPreference");
还有getInt和getBoolean方法。可以使用abp.setting.values对象获取所有的值。注意,如果在服务端更改了设置,客户端不会知道更改,除非页面刷新,设置可以以某种方式重新加载或者使用代码手动更新。
更改设置
ISettingManager定义了ChangeSettingForApplicationAsync、ChangeSettingForTenantAsync 和ChangeSettingForUserAsync 方法(和异步版本)用来更改应用、租户、用户的设置。
关于缓存
设置管理器在服务端缓存设置。所以,我们可以使用仓储或数据库更新查询直接更改设置值。