Ricerca…


Riflessione robusta usando le citazioni di F #

La riflessione è utile ma fragile. Considera questo:

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

I problemi con questo tipo di codice sono:

  1. Il codice non funziona perché ci sono diversi overload di String.StartsWith
  2. Anche se non ci sarebbero sovraccarichi in questo momento, le versioni successive della libreria potrebbero aggiungere un sovraccarico che causa un arresto anomalo del runtime
  3. Strumenti di refactoring come i Rename methods sono infranti di riflessione.

Ciò significa che si verifica un arresto anomalo del runtime per qualcosa che è noto in fase di compilazione. Sembra inopportuno.

Utilizzando le citazioni di F# è possibile evitare tutti i problemi di cui sopra. Definiamo alcune funzioni di supporto:

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

Usiamo le funzioni in questo modo:

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

Questo stampa:

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

<@ ... @> significa che invece di eseguire l'espressione all'interno di F# genera un albero di espressioni che rappresenta l'espressione. <@ "".StartsWith "" @> genera un albero di espressioni simile al seguente: Call (Some (Value ("")), StartsWith, [Value ("")]) . Questo albero di espressioni corrisponde a ciò che getMethodInfo aspetta e restituirà le informazioni sul metodo corretto.

Questo risolve tutti i problemi sopra elencati.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow