【问题标题】:Functional way of handling configuration for a library处理库配置的功能方式
【发布时间】:2021-03-09 06:43:45
【问题描述】:

在 C# 中,库可能会公开您使用 DI 容器提供的实现的接口,实现此功能的方法是什么?我想在库(“库范围”)中进行一些可配置的操作,并能够从主代码中进行设置。

【问题讨论】:

  • 通常在实践中证明,库中只有一两个函数实际上需要配置。所以通常的做法是将配置作为参数传递。如果您确实确定您的库有许多需要配置的功能,您可以考虑将其实现为接口。无论如何,你需要更清楚你真正想要做什么。在 C# 中,依赖注入是默认的首选实践,但在函数式编程中却不是,因此您必须真正考虑是否要这样做。

标签: f# functional-programming


【解决方案1】:

您当然仍然可以在 F# 中使用接口和 DI 容器。但是,函数式编程提供的其他方法也可能对您有用。一些选项可能是:

部分应用:您在一个模块中有一组函数,它们将配置信息作为它们的第一个参数(例如,作为记录类型)。然后,您可以部分应用这些函数,仅传递配置,返回仅采用剩余参数的函数。例如:

type Config =
    {
        ConnectionString: string
        SuperMode: bool
        NumberOfWidgets: int
    }

module Library =
    let login (config: Config) userName passwordHash =
        // do stuff
        ()

    let createWidget (config: Config) widgetName widgetValue =
        // do stuff
        ()

let config = {ConnectionString = "localhost"; SuperMode = true; NumberOfWidgets = 3}

let configuredLogin = Library.login config // configuredLogin is a function taking userName and passwordHash
let configuredCreateWidget = Library.createWidget config // configuredCreateWidget is a function taking widgetName and widgetValu

闭包:您有一个函数,它接受配置并返回一个或多个其他函数,这些函数关闭配置并在调用时使用它。例如:

let applyConfig (config: Config) =
    (fun userName passwordHash -> 
        Library.login config userName passwordHash), // do login using the config
    (fun widgetName widgetValue ->
        Library.createWidget config widgetName widgetValue) // create the widget using the config

let login, createWidget = applyConfig config // Returns functions that close over the Config and use it when called

选择最适合您需求的方法,不要仅仅因为它不“实用”而排除使用您熟悉的经过验证的方法。

【讨论】:

    猜你喜欢
    • 2016-10-09
    • 2021-08-18
    • 2015-09-25
    • 1970-01-01
    • 2023-03-04
    • 2020-08-26
    • 1970-01-01
    • 2021-02-06
    相关资源
    最近更新 更多