2009-11-03 3 views
4

F # interactive는 WinForm 또는 Wpf 창을 실행할 수있는 강력한 개발 도구입니다. 은 임의의 코드를 호출합니다.f # 대화 형을 사용하여 개인 필드/메서드/속성에 액세스하는 방법

이렇게하면 'try-before-you code'방식을 사용할 수 있습니다.

매우 자주/명시하고

  • 호출/개인 보호 방법
  • 액세스를 '경계 파괴'이것을 달성하기 위해

이 있습니까 해결 방법을 private 필드와 속성을 변경하려면 ?

답변

8

FSI는 이에 대한 특별한 지원을 제공하지 않지만 원하는 것을하기 위해 반사를 사용할 수 있습니다.

open System.Reflection 
let field = typeof<MyType>.GetField("fieldName", BindingFlags.NonPublic ||| BindingFlags.Instance) 
field.SetValue(myInstance, newVal) 

더 쉽게 진행할 수 있도록 메소드 나 연산자를 정의 할 수 있습니다. 예를 들어 당신은 private 필드에 할당 F #의 동적 할당 연산자를 설정할 수 있습니다

let (?<-) o s v = 
    let field = (o.GetType()).GetField(s, BindingFlags.NonPublic ||| BindingFlags.Instance) 
    field.SetValue(o,v) 

myInstance?fieldName <- newVal (* Note: no quotes around fieldName here *) 

다음은 공공 또는 민간 필드, 속성 또는 메서드를 해결하기 위해 일부 원유 코드입니다. 이것이 실패 할 수있는 방법은 많습니다 (특히 오버로드 된 메서드에서이 메서드를 사용하려고하면 작동하지 않습니다). 테스트 및 작품

let (t:System.Type) = "test"?GetType()?BaseType 
+0

+1,이 동적 같은 메서드와 속성을 호출 할 수 있습니다와

open System open System.Reflection open Microsoft.FSharp.Reflection type DynamicHelper = static member MkMethod<'t,'u> (mi:MethodInfo) o : 't -> 'u= let typ = typeof<'t> fun t -> let args = if (typ = typeof<unit>) then [||] else if not (FSharpType.IsTuple typ) then [| box t |] else FSharpValue.GetTupleFields t mi.Invoke(o, args) :?> 'u let (?) (o:'a) s : 'b = let ty = o.GetType() let field = ty.GetField(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic) if field <> null then field.GetValue(o) :?> 'b else let prop = ty.GetProperty(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic) if prop <> null then prop.GetValue(o, null) :?> 'b else let meth = ty.GetMethod(s, BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic) let d,r = FSharpType.GetFunctionElements(typeof<'b>) typeof<DynamicHelper>.GetMethod("MkMethod").MakeGenericMethod([|d;r|]).Invoke(null, [| box meth; box o |]) :?> 'b 

. – gradbot

관련 문제