【问题标题】:Is there a way to use F# record types to extract the appsettings.json configuration?有没有办法使用 F# 记录类型来提取 appsettings.json 配置?
【发布时间】:2019-10-19 22:10:50
【问题描述】:

长话短说,当我使用类似 C# 的类时,我可以将 appsettings.json 提取为 Configuration 类型:

type Connection() =
    member val Host = Unchecked.defaultof<string> with get,set
    member val Port = Unchecked.defaultof<int> with get,set
    member val UserName = Unchecked.defaultof<string> with get,set
    member val Password = Unchecked.defaultof<string> with get,set

type Configuration() =
    member val RabbitMQ = Unchecked.defaultof<Connection> with get,set
    member val PostgreSQL = Unchecked.defaultof<Connection> with get,set

let fetchConfiguration =
        let builder = (new ConfigurationBuilder())
                          .SetBasePath(Directory.GetCurrentDirectory())
                          .AddJsonFile("appsettings.json", true, true)
                          .AddEnvironmentVariables(); 
        let configurationRoot = builder.Build();
        let configuration = new Configuration()
        configurationRoot.Bind(configuration)
        configuration

但是当使用 F# 记录类型时:


type Connection = {
    Host: string
    Port: int32
    Username: string
    Password: string
}

type Configuration = {
    RabbitMQ: Connection
    PostgreSQL: Connection
}

let fetchConfiguration =
        let builder = (new ConfigurationBuilder())
                          .SetBasePath(Directory.GetCurrentDirectory())
                          .AddJsonFile("appsettings.json", true, true)
                          .AddEnvironmentVariables(); 
        let configurationRoot = builder.Build();
        let configuration = {
            RabbitMQ = {
                Host = Unchecked.defaultof<string>
                Port = Unchecked.defaultof<int>
                Username = Unchecked.defaultof<string>
                Password = Unchecked.defaultof<string>
            }
            PostgreSQL = {
                Host = Unchecked.defaultof<string>
                Port = Unchecked.defaultof<int>
                Username = Unchecked.defaultof<string>
                Password = Unchecked.defaultof<string>
            }
        }
        configurationRoot.Bind(configuration)
        configuration

我最终得到的配置与我在调用“绑定”方法之前给出的值没有什么不同(即使我没有任何异常),基本上就像什么都没发生一样。

注意:当我使用以下默认值时,我的行为相同:

let configuration = {
    RabbitMQ = Unchecked.defaultof<Connection>
    PostgreSQL = Unchecked.defaultof<Connection>
}

【问题讨论】:

  • 将类型名称Configuration 用于您自己的设置类型是一个坏主意,并且只会使试图阅读您的代码的人感到困惑。在任何情况下,F# 记录都是不可变的。创建它们后,您将无法更改它们的属性。在任何情况下您都不需要使用Bind,您可以使用Get&lt;T&gt; 来检索强类型设置类。
  • 连接和配置记录上的 [] 属性可能会有所帮助。这告诉编译器在成员实现上添加属性设置器,以便执行反序列化等操作的库可以单独设置成员。
  • @Panagiotis Kanavos Configuration 被故意选择用于此 SO 帖子,而不是在实际生产代码中。 F# 记录是不可变的,但取决于序列化程序,可以利用幕后创建的构造函数(至少在 Marten 中它似乎可以工作)。 Get&lt;T&gt; 仅表明反序列化器正在寻找无参数构造函数。但是,当在记录类型上设置 [&lt;CLIMutable&gt;] 属性时,它会起作用。
  • @Wallace Kelly 好用!
  • @EhouarnPerret 仍然让我感到困惑,直到我意识到 Configuration 是一个随机类。 Configuration 是在启动配置方法中使用的 IConfiguration 变量的通用名称。

标签: c# f# default-value appsettings


【解决方案1】:

感谢上面的 cmets,解决方案只是将 [&lt;CLIMutable&gt;] 属性设置为 F# 记录类型:

[<CLIMutable>]
type Connection = {
    Host: string
    Port: int32
    Username: string
    Password: string
}

[<CLIMutable>]
type Configuration = {
    RabbitMQ: Connection
    PostgreSQL: Connection
}

let fetchConfiguration =
        let builder = (new ConfigurationBuilder())
                          .SetBasePath(Directory.GetCurrentDirectory())
                          .AddJsonFile("appsettings.json", true, true)
                          .AddEnvironmentVariables(); 
        let configurationRoot = builder.Build();
        configurationRoot.Get<Configuration>()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多