Dependency injection 将函数注入到计算表达式中

Dependency injection 将函数注入到计算表达式中,dependency-injection,functional-programming,f#,Dependency Injection,Functional Programming,F#,下面的代码示例来自Scott Wlaschin的站点 是否有方法将函数而不是printfn注入LoggingBuilder()?您只需向生成器类型添加一个参数即可: type LoggingBuilder(lf: obj -> unit) = let log p = lf p member this.Bind(x, f) = log x f x member this.Return(x) = x let lo

下面的代码示例来自Scott Wlaschin的站点


是否有方法将函数而不是
printfn
注入
LoggingBuilder()

您只需向生成器类型添加一个参数即可:

type LoggingBuilder(lf: obj -> unit) =
    let log p = lf p

    member this.Bind(x, f) = 
        log x
        f x

    member this.Return(x) = 
        x

let logger = new LoggingBuilder(printfn "expression is %A")
如果您想使输入类型比
obj
更具体,可以将生成器设置为通用

type LoggingBuilder<'a>(lf: 'a -> unit) =
    ...

let logger = new LoggingBuilder<int>(printfn "Got %i")
类型日志生成器单元)=
...
let logger=new LoggingBuilder(printfn“Got%i”)

如果您打算用诸如的记录器替换
printfn
,您可以使用
Printf.ksprintf

open NLog
open NLog.Config
open NLog.Targets

let private logger =
    let config = new LoggingConfiguration()
    let consoleTarget = new ColoredConsoleTarget()
    config.AddTarget("console", consoleTarget)
    consoleTarget.Layout <- Layouts.SimpleLayout.FromString
        @"${longdate}|${level:uppercase=true}|${logger}|${message}"

    let rule = new LoggingRule("*", LogLevel.Debug, consoleTarget)
    config.LoggingRules.Add rule

    LogManager.Configuration <- config
    LogManager.GetLogger "MyLogger"

type LoggingBuilder(lf: string -> unit) =
    let log format =
        let doAfter (s: string) = lf s
        Printf.ksprintf doAfter format

    member this.Bind(x, f) = 
        log "%A" x
        f x

    member this.Return(x) = 
        x

let logger = new LoggingBuilder(logger.Info)
打开NLog
打开NLog.Config
开放式非直瞄目标
让私人记录器=
let config=new LoggingConfiguration()
让consoleTarget=new ColoredConsoleTarget()
config.AddTarget(“控制台”,控制台获取)

控制台,谢谢!我有一个简短的后续问题:计算表达式是否可以在没有类的情况下合成,即
LoggingBuilder
是否可以是一种非类的类型?@lejon-我不确定你的意思,你想让你的生成器成为一个结构体吗?不,但类似
let logger=LoggingBuilder logFn
的东西似乎更。。实际上,您可以像这样调用构造函数,因此无需更改类型定义。但是如果您愿意,您也可以使用
类型LoggingBuilder unit
,这也很有效。
open NLog
open NLog.Config
open NLog.Targets

let private logger =
    let config = new LoggingConfiguration()
    let consoleTarget = new ColoredConsoleTarget()
    config.AddTarget("console", consoleTarget)
    consoleTarget.Layout <- Layouts.SimpleLayout.FromString
        @"${longdate}|${level:uppercase=true}|${logger}|${message}"

    let rule = new LoggingRule("*", LogLevel.Debug, consoleTarget)
    config.LoggingRules.Add rule

    LogManager.Configuration <- config
    LogManager.GetLogger "MyLogger"

type LoggingBuilder(lf: string -> unit) =
    let log format =
        let doAfter (s: string) = lf s
        Printf.ksprintf doAfter format

    member this.Bind(x, f) = 
        log "%A" x
        f x

    member this.Return(x) = 
        x

let logger = new LoggingBuilder(logger.Info)