FsConfig 4.1.0
dotnet add package FsConfig --version 4.1.0
NuGet\Install-Package FsConfig -Version 4.1.0
<PackageReference Include="FsConfig" Version="4.1.0" />
paket add FsConfig --version 4.1.0
#r "nuget: FsConfig, 4.1.0"
// Install FsConfig as a Cake Addin #addin nuget:?package=FsConfig&version=4.1.0 // Install FsConfig as a Cake Tool #tool nuget:?package=FsConfig&version=4.1.0
FsConfig
FsConfig 是一个用于从环境变量和 AppSettings 中读取配置数据并具有类型安全性的 F# 库
为何选择 FsConfig?
要理解 FsConfig,让我们从 FsTweet 应用程序的一个用例来看。
FsTweet 应用程序遵循 十二要素应用 指南来管理配置数据。在应用程序引导过程中,它从相应的环境变量中检索其十个配置参数。
open System
let main argv =
let fsTweetConnString =
Environment.GetEnvironmentVariable "FSTWEET_DB_CONN_STRING"
let serverToken =
Environment.GetEnvironmentVariable "FSTWEET_POSTMARK_SERVER_TOKEN"
let senderEmailAddress =
Environment.GetEnvironmentVariable "FSTWEET_SENDER_EMAIL_ADDRESS"
let env =
Environment.GetEnvironmentVariable "FSTWEET_ENVIRONMENT"
let streamConfig : GetStream.Config = {
ApiKey =
Environment.GetEnvironmentVariable "FSTWEET_STREAM_KEY"
ApiSecret =
Environment.GetEnvironmentVariable "FSTWEET_STREAM_SECRET"
AppId =
Environment.GetEnvironmentVariable "FSTWEET_STREAM_APP_ID"
}
let serverKey =
Environment.GetEnvironmentVariable "FSTWEET_SERVER_KEY"
let port =
Environment.GetEnvironmentVariable "PORT" |> uint16
// ...
尽管代码片段完成这项工作,但仍有一些不足之处。
- 代码冗长。
- 没有错误处理来处理值缺失或错误值的情况。
- 显式类型转换
借助 FsConfig,我们可以通过将配置数据指定为 F# Record 类型来克服这些限制。
type StreamConfig = {
Key : string
Secret : string
AppId : string
}
[<Convention("FSTWEET")>]
type Config = {
DbConnString : string
PostmarkServerToken : string
SenderEmailAddress : string
ServerKey : string
Environment : string
[<CustomName("PORT")>]
Port : uint16
Stream : StreamConfig
}
然后可以通过一次函数调用读取所有相关的环境变量,具有类型安全和错误处理!
let main argv =
let config =
match EnvConfig.Get<Config>() with
| Ok config -> config
| Error error ->
match error with
| NotFound envVarName ->
failwithf "Environment variable %s not found" envVarName
| BadValue (envVarName, value) ->
failwithf "Environment variable %s has invalid value %s" envVarName value
| NotSupported msg ->
failwith msg
支持的数据类型
FsConfig 支持以下数据类型,并利用它们各自的 TryParse
函数进行类型转换。
Int16
,Int32
,Int64
,UInt16
,UInt32
,UInt64
Byte
,SByte
Single
,Double
,Decimal
Char
,String
Bool
TimeSpan
、DateTimeOffset
、DateTime
Guid
枚举
- 上述所有类型的
list
- 上述所有类型的
option
选项类型
FsConfig 允许我们使用 option
类型指定可选配置参数。在之前的示例中,如果配置参数 Port
是可选的,我们可以定义如下
type Config = {
...
- Port : uint16
+ Port : uint16 option
}
区分联合类型
FsConfig 支持只有情况单独的区分联合类型。
type Color =
| Red
| Green
| Blue
type Config = {
ConsoleColor : Color
}
通过此配置声明,FsConfig 读取环境变量
CONSOLE_COLOR
并填充类型为Color
的ConsoleColor
字段。
还支持区分联合类型的列表!
列表类型
FsConfig 还支持 list
类型,并且它期望用逗号分隔的单独值。
例如,要获取多个端口,我们可以将配置定义如下
type Config = {
Port : uint16 list
}
然后通过环境变量 PORT
使用值 8084,8085,8080
。
如果需要,可以通过使用 ListSeparator
属性更改列表的默认分隔符。
[<Convention("MYENV")>]
type CustomListSeparatorSampleConfig = {
ProcessNames : string list
[<ListSeparator(';')>]
ProcessIds : uint16 list
[<ListSeparator('|')>]
PipedFlow : int list
}
通过此配置声明,FSConfig 可以从 App.settings 中读取以下条目。
<add key="MYENVProcessNames" value="conhost.exe,gitter.exe"/>
<add key="MYENVProcessIds" value="4700;15680"/>
<add key="MYENVPipedFlow" value="4700|15680|-1" />
下述定义类似的结构将允许解析独立的列表。
type IntListUsingSemiColonsConfig = {
[<ListSeparator(';')>]
IntListUp : int list
}
例如,一个包含以下环境的环境
INT_LIST_UP=42;43;44
记录类型
如初始示例所示,FsConfig 允许我们将类似的配置组合成一个记录类型。
type AwsConfig = {
AccessKeyId : string
DefaultRegion : string
SecretAccessKey : string
}
type Config = {
Aws : AwsConfig
}
通过此配置声明,FsConfig 读取环境变量
AWS_ACCESS_KEY_ID
、AWS_SECRET_ACCESS_KEY
和AWS_DEFAULT_REGION
并填充类型为AwsConfig
的Aws
字段。
默认值
如果您希望在没有字段值的情况下使用默认值,您可以使用 DefaultValue
属性。
type Config = {
[<DefaultValue("8080")>]
HttpServerPort : int16
[<DefaultValue("Server=localhost;Port=5432;Database=FsTweet;User Id=postgres;Password=test;")>]
DbConnectionString: string
}
环境变量名称约定 & 自定义
默认情况下,FsConfig 遵循下划线加首字母大写的约定,例如 UPPER_CASE
,用于派生环境变量名称。
type Config = {
ServerKey : string
}
使用此配置声明,FsConfig 读取环境变量
SERVER_KEY
并填充ServerKey
字段
要指定环境变量中的自定义前缀,我们可以使用 Convention
属性。
[<Convention("FSTWEET")>]
type Config = {
ServerKey : string
}
对于此配置声明,FsConfig 读取环境变量
FSTWEET_SERVER_KEY
并填充ServerKey
字段。
我们还可以使用 Convention
属性的可选字段 Separator
来覆盖分隔符字符 _
。
[<Convention("FSTWEET", Separator="-")>]
type Config = {
ServerKey : string
}
在这种情况下,FsConfig 将环境变量名称派生为
FSTWEET-SERVER-KEY
。
如果环境变量名称不遵循约定,我们可以在字段级别使用 CustomName
属性来覆盖环境变量名称。
type Config = {
[<CustomName("MY_SERVER_KEY")>]
ServerKey : string
}
在此,FsConfig 使用环境变量名称
MY_SERVER_KEY
来获取 ServerKey。
我们还可以通过在调用 Get
函数时传递一个高阶函数来简化(或控制)环境变量名称的生成。
open FsConfig
// Prefix -> string -> string
let lowerCaseConfigNameCanonicalizer (Prefix prefix) (name : string) =
let lowerCaseName = name.ToLowerInvariant()
if String.IsNullOrEmpty prefix then
name.ToLowerInvariant()
else
sprintf "%s-%s" (prefix.ToLowerInvariant()) lowerCaseName
[<Convention("FSTWEET")>]
type Config = {
ServerKey : string
}
let main argv =
let config =
match EnvConfig.Get<Config> lowerCaseConfigNameCanonicalizer with
| Ok config -> config
| Error error -> failwithf "Error : %A" error
在此场景中,FsConfig 计算环境变量名称为
fstweet-server-key
。
获取单个环境变量
FsConfig 还支持通过显式指定环境变量名称来直接读取值
EnvConfig.Get<decimal> "MY_APP_INITIAL_BALANCE" // Result<decimal, ConfigParseError>
应用配置
FsConfig 支持适用于 DotNet Core 和非 DotNet Core 应用程序的应用程序配置。
DotNet Core 应用程序(从 V2.0.0 开始支持)
非 DotNet Core 应用程序(仅支持 V0.0.6 或以下版本)
DotNet Core 配置(从 V2.0.0 开始支持)
FsConfig 通过依赖于 IConfigurationRoot 来抽象配置提供程序。
let configurationRoot : IConfigurationRoot = // ...
let appConfig = new AppConfig(configurationRoot)
创建一个实例 appConfig
(类型为 FsConfig 的 AppConfig
)后,可以使用它按照以下方式读取配置值
// Reading Primitive
let result =
appConfig.Get<int> "processId" // Result<int, ConfigParseError>
// A Sample Record
type SampleConfig = {
ProcessId : int
ProcessName : string
}
// Reading a Record type
let result =
appConfig.Get<SampleConfig> () // Result<SampleConfig, ConfigParseError>
// A Sample Nested Record
type AwsConfig = {
AccessKeyId : string
DefaultRegion : string
SecretAccessKey : string
}
type Config = {
MagicNumber : int
Aws : AwsConfig
}
// Reading a Nested Record type
let result =
appConfig.Get<Config> () // Result<Config, ConfigParseError>
以下是根据文件类型创建 configurationRoot
并使用 FsConfig 读取值的示例。
JSON
{
"processId" : "123",
"processName" : "FsConfig",
"magicNumber" : 42,
"aws" : {
"accessKeyId" : "Id-123",
"defaultRegion" : "us-east-1",
"secretAccessKey" : "secret123"
},
"colors" : "Red,Green"
}
可以使用以下方法读取此 JSON 文件
// Requires NuGet package
// Microsoft.Extensions.Configuration.Json
let configurationRoot =
ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("settings.json").Build()
let appConfig = new AppConfig(configurationRoot)
let result =
appConfig.Get<Config> () // Result<Config, ConfigParseError>
XML
<Settings>
<ProcessId>123</ProcessId>
<ProcessName>FsConfig</ProcessName>
<MagicNumber>42</MagicNumber>
<Aws>
<AccessKeyId>Id-123</AccessKeyId>
<DefaultRegion>us-east-1</DefaultRegion>
<SecretAccessKey>secret123</SecretAccessKey>
</Aws>
<Colors>Red,Green</Colors>
</Settings>
可以使用以下方法读取此 XML 文件
// Requires NuGet package
// Microsoft.Extensions.Configuration.Xml
let configurationRoot =
ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddXmlFile("settings.xml").Build()
let appConfig = new AppConfig(configurationRoot)
let result =
appConfig.Get<Config> () // Result<Config, ConfigParseError>
INI
ProcessId=123
ProcessName=FsConfig
MagicNumber=42
Colors=Red,Green
[Aws]
AccessKeyId=Id-123
DefaultRegion=us-east-1
SecretAccessKey=secret123
可以使用以下方法读取此 INI 文件
// Requires NuGet package
// Microsoft.Extensions.Configuration.Ini
let configurationRoot =
ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddIniFile("settings.ini").Build()
let appConfig = new AppConfig(configurationRoot)
let result =
appConfig.Get<Config> () // Result<Config, ConfigParseError>
appSettings(仅在 V0.0.6 或以下版本中受支持)
我们可以使用 AppConfig
类型而不是 EnvConfig
类型来读取 appSettings
的值。
FsConfig 使用字段的精确名称来导出 appSettings
键名,并默认不使用分隔符。
type AwsConfig = {
AccessKeyId : string
DefaultRegion : string
SecretAccessKey : string
}
type Config = {
Port : uint16
Aws : AwsConfig
}
let main argv =
let config =
match AppConfig.Get<Config>() with
| Ok config -> config
| Error error -> failwithf "Error : %A" error
上述代码片段会查找具有名称
Port
、AwsAccessKeyId
、AwsDefaultRegion
、AwsSecretAccessKey
的appSettings
值,并将其填充到相应的字段中。
我们对 EnvConfig
所做的所有自定义设置也适用于 AppConfig
。
FsConfig 的工作原理
如果您想了解 FsConfig 的工作原理及其内部结构,那么您可能对我的博客文章感兴趣,该文章深入探讨了 FsConfig 的初始实现,请参考泛型编程如此简单。
反馈
我们所有人都需要愿意给我们反馈的人。这就是我们不断提高的方式——比尔·盖茨。
欢迎您的建议/反馈!
致谢
FsConfig 的灵感来源于 Kelsey Hightower 的 golang 库 envconfig。
FsConfig 使用 Eirik Tsarpalis 的 TypeShape 库进行泛型编程。
维护者
产品 | 版本 兼容的和额外的计算目标框架版本。 |
---|---|
.NET | net5.0 已计算。 net5.0-windows 已计算。 net6.0 已计算。 net6.0-android 已计算。 net6.0-ios 已计算。 net6.0-maccatalyst 已计算。 net6.0-macos 已计算。 net6.0-tvos 已计算。 net6.0-windows 已计算。 net7.0 已计算。 net7.0-android 已计算。 net7.0-ios 已计算。 net7.0-maccatalyst 已计算。 net7.0-macos 已计算。 net7.0-tvos 已计算。 net7.0-windows 已计算。 net8.0 已计算。 net8.0-android 已计算。 net8.0-browser 已计算。 net8.0-ios 已计算。 net8.0-maccatalyst 已计算。 net8.0-macos 已计算。 net8.0-tvos 已计算。 net8.0-windows 已计算。 |
.NET Core | netcoreapp2.0 已计算。 netcoreapp2.1 已计算。 netcoreapp2.2 已计算。 netcoreapp3.0 已计算。 netcoreapp3.1 已计算。 |
.NET Standard | netstandard2.0 兼容。 netstandard2.1 已计算。 |
.NET Framework | net461 已计算。 net462 已计算。 net463 已计算。 net47 已计算。 net471 已计算。 net472 已计算。 net48 已计算。 net481 已计算。 |
MonoAndroid | monoandroid已计算。 |
MonoMac | monomac已计算。 |
MonoTouch | monotouch已计算。 |
Tizen | tizen40已计算。 tizen60已计算。 |
Xamarin.iOS | xamarinios已计算。 |
Xamarin.Mac | xamarinmac已计算。 |
Xamarin.TVOS | xamarintvos已计算。 |
Xamarin.WatchOS | xamarinwatchos已计算。 |
-
.NETStandard 2.0
- FSharp.Core (>= 6.0.0)
- Microsoft.Extensions.Configuration (>= 6.0.0)
- TypeShape (>= 10.0.0)
NuGet包
此包没有被任何NuGet包使用。
GitHub存储库
此包没有被任何流行的GitHub存储库使用。
版本 | 下载 | 最后更新 |
---|---|---|
4.1.0 | 9,157 | 10/24/2023 |
4.0.0 | 11,235 | 6/18/2023 |
3.1.0 | 65,858 | 7/25/2021 |
3.0.0 | 24,580 | 1/30/2021 |
2.1.6 | 20,119 | 4/26/2020 |
2.1.5 | 9,521 | 11/11/2019 |
2.1.4 | 1,145 | 10/18/2019 |
2.1.3 | 3,889 | 6/9/2019 |
2.1.2 | 719 | 5/24/2019 |
2.0.2 | 2,219 | 8/12/2018 |
2.0.1 | 908 | 7/27/2018 |
2.0.0 | 1,261 | 6/26/2018 |
2.0.0-beta1 | 783 | 6/6/2018 |
1.2.1 | 1,261 | 5/29/2018 |
1.1.2 | 1,004 | 5/29/2018 |
1.1.1 | 1,034 | 5/10/2018 |
1.1.0 | 930 | 5/7/2018 |
1.0.0 | 1,772 | 4/28/2018 |
1.0.0-beta1 | 954 | 4/28/2018 |
0.0.6 | 1,185 | 4/27/2018 |
0.0.5 | 1,007 | 2/23/2018 |
0.0.4 | 979 | 2/5/2018 |
0.0.3 | 1,023 | 2/3/2018 |
0.0.2 | 975 | 2/3/2018 |
0.0.1 | 1,035 | 2/1/2018 |
## [4.1.0] - 2023-10-24
[4.1.0]: https://github.com/demystifyfp/FsConfig/compare/v4.0.0...v4.1.0
### 添加
- 由[queil](https://github.com/queil)提供的可选子部分支持