设置允许扩展作者定义最终用户可配置的值以影响扩展的行为。
扩展可以读取、写入或观察设置值。 设置在类别层次结构中组织,并提供对文档和验证的丰富支持。
定义设置
若要开始,请按照 创建您的第一个扩展 教程。
创建扩展后,可以将设置定义添加到扩展中的任何类:
#pragma warning disable VSEXTPREVIEW_SETTINGS // The settings API is currently in preview and marked as experimental
private static class SettingDefinitions
{
[VisualStudioContribution]
private static SettingCategory MyCategory { get; } = new("myCategory", "My Category");
[VisualStudioContribution]
private static Setting.Boolean MySetting { get; } = new("mySetting", "My Setting", MyCategory, defaultValue: false);
}
上面的代码定义名为 mySetting
myCategory
类别下的 true/false(布尔值)设置,默认值为 false。 请注意,设置和类别都具有 VisualStudioContribution
属性。
向用户显示设置和类别的显示名称时,建议使用本地化字符串(请参阅 本地化文档):
[VisualStudioContribution]
private static SettingCategory MyCategory { get; } = new("myCategory", "%MyExtension.SettingDefinitions.MyCategory%"){
Description = "%MyExtension.SettingDefinitions.MyCategory.Description%",
GenerateObserverClass = true,
};
[VisualStudioContribution]
private static Setting.Boolean MySetting { get; } = new("mySetting", "%MyExtension.SettingDefinitions.MySetting%", MyCategory, defaultValue: false){
Description = "%MyExtension.SettingDefinitions.MySetting.Description%",
};
还可以嵌套类别:
[VisualStudioContribution]
private static SettingCategory ParentCategory { get; } = new("parentCategory", "Parent Category");
[VisualStudioContribution]
private static SettingCategory ChildCategory { get; } = new("childCategory", "Child Category", ParentCategory);
[VisualStudioContribution]
private static Setting.Boolean MySetting { get; } = new("mySetting", "My Setting", ChildCategory, defaultValue: false);
读取和监视设置值
当 GenerateObserverClass
设置为 SettingCategory
定义中的 true
时,将生成观察程序类。 观察器可用于读取和监视类别中的设置。
可以通过在 Extension
类 InitializeServices
方法中调用 serviceCollection.AddSettingsObservers();
,使观察程序可用于依赖项注入:
protected override void InitializeServices(IServiceCollection serviceCollection)
{
serviceCollection.AddSettingsObservers();
base.InitializeServices(serviceCollection);
}
然后,可以从通过依赖项注入创建的任何组件(如命令或工具窗口)使用观察程序:
public MyToolWindow(Settings.MyCategoryObserver settingsObserver)
{
this.settingsObserver = settingsObserver;
}
private async Task DoSomethingAsync()
{
var settingsSnapshot = await this.settingsObserver.GetSnapshotAsync(cancellationToken);
bool mySetting = settingsSnapshot.MySetting.ValueOrDefault(defaultValue: true);
}
MyCategoryObserver
类在扩展命名空间的 Settings
子命名空间下生成。
当类别中的任何值发生更改时,也可以使用观察程序引发事件。
public MyToolWindow(Settings.MyCategoryObserver settingsObserver)
{
settingsObserver.Changed += this.SettingsObserver_ChangedAsync;
}
private async Task SettingsObserver_ChangedAsync(Settings.MyCategorySnapshot settingsSnapshot)
{
this.MySetting = settingsSnapshot.MySetting.ValueOrDefault(defaultValue: true);
...
}
Changed
事件处理程序始终至少被调用一次,且使用当前设置值,因此无需读取初始值。
设定一个场景
在某些情况下,扩展可能需要更改设置的值。 可以通过批量写入操作来实现,该操作允许同时更新多个设置。
var writeResult = await Extensibility.Settings().WriteAsync(
batch =>
{
batch.WriteSetting(ExtensionEntrypoint.MySetting1, value: true);
batch.WriteSetting(ExtensionEntrypoint.MySetting2, value: "foo");
},
description: "Updating the settings' value to true and `foo`",
cancellationToken);
传递给 WriteAsync
调用的说明应本地化。
读取设置
可以从扩展中的任何位置访问设置的值。 虽然最好使用观察程序持续监视设置值,但可能会出现扩展不需要持续监视整个设置类别的情况。 下面的代码演示如何从命令的处理程序读取上面定义的设置。
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
var result = await Extensibility.Settings().ReadEffectiveValueAsync(SettingDefinitions.MySetting, cancellationToken);
bool value = result.ValueOrDefault(defaultValue: false);
...
}
请注意,ReadEffectiveValueAsync
返回的是下列之一的 SettingValue<>
:
- 设置的当前值
- 为设置声明的默认值(如果从未为设置分配值)
- 读取期间发生的错误。
通常,你会利用 ValueOrDefault()
方法来获取检索到的设置值或调用时提供的回退值。
还可以利用 ReadEffectiveValuesAsync
方法通过单个调用读取多个设置。
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
var results = await Extensibility.Settings().ReadEffectiveValuesAsync(
[ExtensionEntrypoint.MySetting1, ExtensionEntrypoint.MySetting2],
cancellationToken);
var value = results.ValueOrDefault(ExtensionEntrypoint.MySetting1, defaultValue: false);
...
}
监视某个设置
在不使用观察者的情况下,您也可以监视设置的值:
IDisposable disposeToEndSubscription =
await Extensibility.Settings().SubscribeAsync(
ExtensionEntrypoint.MySetting,
cancellationToken,
changeHandler: result =>
{
var value = result.ValueOrDefault(defaultValue: false);
...
});
SubscribeAsync
更改处理程序保证确保至少用设置的当前值调用一次。
设置值和设置元数据的类型
设置不限于布尔值类型。 可以使用多种类型定义它们,其中包括:
Setting.Boolean
-
Setting.Decimal
(对于浮点值) -
Setting.Enum
(对于多个选项,每个选项都由本地化字符串表示) -
Setting.FormattedString
(日期、时间、IP 地址、电子邮件、URI、文件和目录路径) Setting.Integer
Setting.String
Setting.EnumArray
Setting.FormattedStringArray
Setting.StringArray
-
Setting.ObjectArray
(一系列项,每个项都具有多个类型属性)
每种类型都允许定义适当的验证规则和其他元数据,例如向最终用户显示文档。 这是一个更完整的字符串类型设置定义的示例:
[VisualStudioContribution]
private static Setting.String MyStringSetting { get; } = new(
"myStringSetting",
"%MyExtension.SettingDefinitions.MyStringSetting%",
MyCategory,
defaultValue: "")
{
MaxStringLength = 100,
Description = "%MyExtension.SettingDefinitions.MyStringSetting.Description%",
};
这是枚举设置的定义示例:
[VisualStudioContribution]
private static Setting.Enum MyEnumSetting { get; } = new(
"myEnumSetting",
"%MyExtension.SettingDefinitions.MyEnumSetting%",
MyCategory,
[
new("true", "%MyExtension.SettingDefinitions.MyEnumSetting.True%"),
new("false", "%MyExtension.SettingDefinitions.MyEnumSetting.False%"),
new("disabled", "%MyExtension.SettingDefinitions.MyEnumSetting.Disabled%"),
],
defaultValue: "disabled")
{
Description = "%MyExtension.SettingDefinitions.MyEnumSetting.Description%",
};
相关内容
有关详细信息,请参阅 设置 API 文档。