수색…


F # 견적을 사용한 강력한 반영

반사는 유용하지만 깨지기 쉽습니다. 이걸 고려하세요:

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

이러한 종류의 코드에 대한 문제점은 다음과 같습니다.

  1. String.StartsWith 여러 오버로드가 있기 때문에 코드가 작동하지 않습니다 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