Как реализовать вычислительное выражение с помощью пользовательских операций и выполнения операторов - PullRequest
0 голосов
/ 24 февраля 2019

Я пытаюсь реализовать 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
}
...