如何通过自定义操作和语句执行来实现计算表达式

时间:2019-02-24 16:32:52

标签: f# system.diagnostics computation-expression

我正在尝试实现diagnostics计算表达式以使用System.Diagnostics.DiagnosticSource NuGet记录活动和事件。

但是我无法弄清楚我的计算表达式如何在两次调用自定义操作之间执行规则语句。

这是我目前的实现方式,并提供了我希望如何使用它的示例。 最后,它必须将整个表达式包装到try-finally中,并使用最后一个上下文停止该活动。

open System.Diagnostics

[<Struct>]
type DiagnosticsState = {
    Activity : Activity voption
    Context : obj
}
with
    member this.StartActivity (source : DiagnosticSource) activityName =
        if ValueOption.isSome this.Activity
            then invalidOp "Use yield to stop previous activity"
        let activity =
            if source.IsEnabled (activityName) then
                let activity = Activity (activityName)
                let eventName = activityName + ".Event"
                if source.IsEnabled (eventName)
                then source.StartActivity (activity, this.Context)
                else activity.Start()
                |> ValueSome
            else ValueNone
        let state = this
        { state with Activity = activity; Context = Unchecked.defaultof<_> }

    member this.StopActivity (source : DiagnosticSource) =
        match this.Activity with
        | ValueSome activity ->
            source.StopActivity (activity, this.Context)
        | ValueNone -> ()

type DiagnosticsBuilder (sourceName) =

    let source = new DiagnosticListener (sourceName) :> DiagnosticSource

    //member __.Zero () =
    //    { Activity = ValueNone; Context = ValueNone }

    member __.Yield (_) =
        { Activity = ValueNone; Context = ValueNone }

    //member __.Combine (state1 : DiagnosticsState, state2 : DiagnosticsState) =
    //    state1.StopActivity source
    //    state2

    //member __.Delay (f) = f()

    member __.For (state, action : _ -> DiagnosticsState) =
        action state

    [<CustomOperation("activity")>]
    member __.Activity (state : DiagnosticsState, activityName) =
        state.StartActivity source activityName

    [<CustomOperation("context")>]
    member __.Context<'Context> (state : DiagnosticsState, context : 'Context) =
        { state with Context = context :> obj }

    [<CustomOperation("event")>]
    member __.Event (state : DiagnosticsState, eventName) =
        if source.IsEnabled (eventName) then
            source.Write(eventName, state.Context)
        state

    member __.Run (state : DiagnosticsState) = state.StopActivity source

let diagnostics = DiagnosticsBuilder "libid";;

diagnostics {
    context "5"
    printf "fdf"
    activity "ace"
    context 5
}

0 个答案:

没有答案