Поиск…


Надежное отражение с использованием кодов F #

Отражение полезно, но хрупко. Учти это:

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

Проблемы с таким кодом:

  1. Код не работает, потому что существует несколько перегрузок String.StartsWith
  2. Даже если бы не было никаких перегрузок прямо сейчас, то более поздние версии библиотеки могут добавить перегрузку, приводящую к сбою во время выполнения
  3. Инструменты рефакторинга, такие как Rename methods разбиты с отражением.

Это означает, что мы получаем сбои во время выполнения для того, что известно время компиляции. Это кажется субоптимальным.

Используя цитаты F# , можно избежать всех вышеперечисленных проблем. Определим некоторые вспомогательные функции:

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

Мы используем следующие функции:

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

Это печатает:

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

<@ ... @> означает, что вместо выполнения выражения внутри F# генерируется дерево выражений, представляющее выражение. <@ "".StartsWith "" @> генерирует дерево выражений, которое выглядит так: Call (Some (Value ("")), StartsWith, [Value ("")]) . Это дерево выражений соответствует getMethodInfo и возвращает правильную информацию о методе.

Это устраняет все перечисленные выше проблемы.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow