Suche…


Robustes Nachdenken durch F # -Zitate

Reflexion ist nützlich, aber fragil. Bedenken Sie:

let mi  = typeof<System.String>.GetMethod "StartsWith"

Die Probleme mit dieser Art von Code sind:

  1. Der Code funktioniert nicht, da String.StartsWith mehrere Überladungen String.StartsWith
  2. Selbst wenn es jetzt keine Überlastungen gibt, können spätere Versionen der Bibliothek eine Überlastung hinzufügen, die einen Laufzeitabsturz verursacht
  3. Refactoring-Tools wie Rename methods durch Reflektion unterbrochen.

Das heißt, wir bekommen eine Laufzeitabsturz für etwas, das als Kompilierzeit bekannt ist. Das scheint suboptimal zu sein.

Mit F# -Zitate können Sie alle oben genannten Probleme vermeiden. Wir definieren einige Hilfsfunktionen:

open FSharp.Quotations
open System.Reflection

let getConstructorInfo (e : Expr<'T>) : ConstructorInfo =
  match e with
  | Patterns.NewObject (ci, _) -> ci
  | _ -> failwithf "Expression has the wrong shape, expected NewObject (_, _) instead got: %A" e


let getMethodInfo (e : Expr<'T>) : MethodInfo =
  match e with
  | Patterns.Call (_, mi, _) -> mi
  | _ -> failwithf "Expression has the wrong shape, expected Call (_, _, _) instead got: %A" e

Wir verwenden die Funktionen wie folgt:

printfn "%A" <| getMethodInfo <@ "".StartsWith "" @>
printfn "%A" <| getMethodInfo <@ List.singleton 1 @>
printfn "%A" <| getConstructorInfo <@ System.String [||] @>

Dies druckt:

Boolean StartsWith(System.String)
Void .ctor(Char[])
Microsoft.FSharp.Collections.FSharpList`1[System.Int32] Singleton[Int32](Int32)

<@ ... @> bedeutet, dass anstelle der Ausführung des Ausdrucks in F# eine Ausdrucksstruktur generiert wird, die den Ausdruck darstellt. <@ "".StartsWith "" @> generiert eine Ausdrucksbaumstruktur, die folgendermaßen aussieht: Call (Some (Value ("")), StartsWith, [Value ("")]) . Diese Ausdrucksbaumstruktur entspricht den getMethodInfo und gibt die korrekten Methodeninformationen zurück.

Dies löst alle oben aufgeführten Probleme.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow