Szukaj…


Solidne odbicie przy użyciu cytatów F #

Odbicie jest przydatne, ale delikatne. Rozważ to:

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

Problemy z tego rodzaju kodem są następujące:

  1. Kod nie działa, ponieważ istnieje kilka przeciążeń String.StartsWith
  2. Nawet jeśli w tej chwili nie wystąpiłyby żadne przeciążenia, późniejsze wersje biblioteki mogłyby dodać przeciążenie powodujące awarię środowiska wykonawczego
  3. Narzędzia do refaktoryzacji, takie jak Rename methods są zepsute.

Oznacza to, że otrzymujemy awarie środowiska wykonawczego dla czegoś, co jest znane z czasu kompilacji. To wydaje się nieoptymalne.

Za pomocą cytatów F# można uniknąć wszystkich powyższych problemów. Definiujemy niektóre funkcje pomocnicze:

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

Korzystamy z takich funkcji:

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

To drukuje:

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

<@ ... @> oznacza, że zamiast wykonywania wyrażenia w F# generuje drzewo wyrażeń reprezentujące wyrażenie. <@ "".StartsWith "" @> generuje drzewo wyrażeń, które wygląda następująco: Call (Some (Value ("")), StartsWith, [Value ("")]) . To drzewo wyrażeń jest zgodne z oczekiwaniami getMethodInfo i zwróci prawidłowe informacje o metodzie.

To rozwiązuje wszystkie problemy wymienione powyżej.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow