Recherche…


Réflexion robuste à l'aide de citations F #

La réflexion est utile mais fragile. Considère ceci:

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

Les problèmes avec ce type de code sont les suivants:

  1. Le code ne fonctionne pas car il y a plusieurs surcharges de String.StartsWith
  2. Même s'il n'y avait pas de surcharge, les versions ultérieures de la bibliothèque pourraient ajouter une surcharge provoquant un plantage à l'exécution
  3. Les outils de refactoring comme les Rename methods sont rompus avec la réflexion.

Cela signifie que nous obtenons un crash à l'exécution pour quelque chose qui est connu à la compilation. Cela semble sous-optimal.

En utilisant les citations F# il est possible d'éviter tous les problèmes ci-dessus. Nous définissons des fonctions d'assistance:

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

Nous utilisons les fonctions comme ceci:

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

Cela imprime:

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

<@ ... @> signifie qu'au lieu d'exécuter l'expression à l'intérieur de F# génère un arbre d'expression représentant l'expression. <@ "".StartsWith "" @> génère un arbre d'expression qui ressemble à ceci: Call (Some (Value ("")), StartsWith, [Value ("")]) . Cet arbre d'expression correspond à ce que getMethodInfo attend et renvoie les informations de méthode correctes.

Cela résout tous les problèmes énumérés ci-dessus.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow